FastAPI 核心机制:分页参数的实现与最佳实践

news/2025/3/13 1:51:49/文章来源:https://www.cnblogs.com/Amd794/p/18769003

title: FastAPI 核心机制:分页参数的实现与最佳实践
date: 2025/3/13
updated: 2025/3/13
author: cmdragon

excerpt:
在构建现代Web应用程序时,分页是一个不可或缺的功能。无论是处理大量数据还是优化用户体验,分页都起到了至关重要的作用。本文将深入探讨如何在FastAPI中实现分页参数(如page、page_size以及总页数计算),并涵盖相关的核心机制、最佳实践、常见问题及解决方案。

categories:

  • 后端开发
  • FastAPI

tags:

  • FastAPI
  • 分页
  • Web开发
  • 数据库查询
  • 性能优化
  • 安全实践
  • 错误处理

image
image

image

扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长

探索数千个预构建的 AI 应用,开启你的下一个伟大创意

1. 分页的基本概念

分页是将大量数据分割成多个小块(即“页”),以便用户或系统可以逐步加载和处理这些数据。在Web应用中,分页通常用于处理数据库查询结果、API响应等场景。常见的分页参数包括:

  • page:当前页码。
  • page_size:每页显示的数据条数。
  • total_pages:总页数。

2. FastAPI中的分页实现

在FastAPI中,分页可以通过查询参数来实现。以下是一个简单的示例,展示了如何在FastAPI中实现分页功能。

from fastapi import FastAPI, Query
from typing import List, Optionalapp = FastAPI()# 模拟数据库数据
fake_items_db = [{"item_name": f"Item {i}"} for i in range(100)]@app.get("/items/")
async def read_items(page: int = Query(1, gt=0), page_size: int = Query(10, gt=0)):start = (page - 1) * page_sizeend = start + page_sizeitems = fake_items_db[start:end]total_items = len(fake_items_db)total_pages = (total_items + page_size - 1) // page_sizereturn {"items": items,"page": page,"page_size": page_size,"total_items": total_items,"total_pages": total_pages,}

在这个示例中,我们定义了两个查询参数pagepage_size,并通过计算startend
来获取当前页的数据。我们还计算了总页数total_pages,并将其包含在响应中。

3. 分页参数的最佳实践

3.1 参数验证

为了确保分页参数的有效性,我们需要对pagepage_size进行验证。FastAPI提供了Query参数验证功能,可以轻松实现这一点。

from fastapi import Query@app.get("/items/")
async def read_items(page: int = Query(1, gt=0), page_size: int = Query(10, gt=0, le=100)):# 分页逻辑pass

在这个示例中,我们使用gt(大于)和le(小于等于)来限制pagepage_size的取值范围。如果用户提供的参数不符合要求,FastAPI会自动返回422
Validation Error。

3.2 默认值设置

为分页参数设置合理的默认值可以提升用户体验。例如,将page_size的默认值设置为10或20,可以避免用户一次性加载过多数据。

@app.get("/items/")
async def read_items(page: int = Query(1, gt=0), page_size: int = Query(10, gt=0, le=100)):# 分页逻辑pass

3.3 总页数计算

总页数的计算公式为:

total_pages = (total_items + page_size - 1) // page_size

这个公式确保了总页数的准确性,即使total_items不能被page_size整除。

4. 数据库查询中的分页

在实际应用中,分页通常与数据库查询结合使用。以下是一个使用SQLAlchemy进行分页查询的示例。

from sqlalchemy.orm import Session
from fastapi import Depends
from .database import SessionLocaldef get_db():db = SessionLocal()try:yield dbfinally:db.close()@app.get("/items/")
async def read_items(page: int = Query(1, gt=0), page_size: int = Query(10, gt=0, le=100),db: Session = Depends(get_db)):start = (page - 1) * page_sizeitems = db.query(Item).offset(start).limit(page_size).all()total_items = db.query(Item).count()total_pages = (total_items + page_size - 1) // page_sizereturn {"items": items,"page": page,"page_size": page_size,"total_items": total_items,"total_pages": total_pages,}

在这个示例中,我们使用offsetlimit来实现分页查询,并通过count方法获取总数据条数。

5. 分页的安全性

5.1 避免SQL注入

在使用原始SQL查询时,必须注意避免SQL注入攻击。SQLAlchemy等ORM框架已经内置了防止SQL注入的机制,但在使用原始SQL时,仍需谨慎。

from sqlalchemy.sql import text@app.get("/items/")
async def read_items(page: int = Query(1, gt=0), page_size: int = Query(10, gt=0, le=100),db: Session = Depends(get_db)):start = (page - 1) * page_sizequery = text("SELECT * FROM items LIMIT :limit OFFSET :offset")items = db.execute(query, {"limit": page_size, "offset": start}).fetchall()total_items = db.execute(text("SELECT COUNT(*) FROM items")).scalar()total_pages = (total_items + page_size - 1) // page_sizereturn {"items": items,"page": page,"page_size": page_size,"total_items": total_items,"total_pages": total_pages,}

在这个示例中,我们使用参数化查询来避免SQL注入。

5.2 数据隐私

在处理敏感数据时,确保分页查询不会泄露隐私信息。例如,避免在分页查询中返回未授权的数据。

6. 性能优化

6.1 索引优化

在数据库查询中,为分页字段(如idcreated_at等)创建索引可以显著提升查询性能。

CREATE INDEX idx_items_created_at ON items (created_at);

6.2 缓存

对于频繁访问的分页数据,可以使用缓存机制(如Redis)来减少数据库查询次数。

from fastapi_cache import FastAPICache
from fastapi_cache.decorator import cache@app.get("/items/")
@cache(expire=60)
async def read_items(page: int = Query(1, gt=0), page_size: int = Query(10, gt=0, le=100)):# 分页逻辑pass

在这个示例中,我们使用fastapi-cache库来缓存分页查询结果,缓存有效期为60秒。

7. 常见错误及解决方案

7.1 422 Validation Error

当分页参数不符合验证规则时,FastAPI会返回422 Validation Error。解决方案是确保分页参数的取值范围正确,并在API文档中明确说明。

@app.get("/items/")
async def read_items(page: int = Query(1, gt=0), page_size: int = Query(10, gt=0, le=100)):# 分页逻辑pass

7.2 500 Internal Server Error

当数据库查询失败或分页逻辑出现错误时,可能会返回500 Internal Server Error。解决方案是捕获异常并返回友好的错误信息。

from fastapi import HTTPException@app.get("/items/")
async def read_items(page: int = Query(1, gt=0), page_size: int = Query(10, gt=0, le=100),db: Session = Depends(get_db)):try:start = (page - 1) * page_sizeitems = db.query(Item).offset(start).limit(page_size).all()total_items = db.query(Item).count()total_pages = (total_items + page_size - 1) // page_sizereturn {"items": items,"page": page,"page_size": page_size,"total_items": total_items,"total_pages": total_pages,}except Exception as e:raise HTTPException(status_code=500, detail=str(e))

在这个示例中,我们捕获了所有异常,并返回500 Internal Server Error。

8. 课后Quiz

  1. 如何避免SQL注入攻击?

    • 使用参数化查询。
    • 避免拼接SQL语句。
    • 使用ORM框架。
  2. 如何优化分页查询的性能?

    • 为分页字段创建索引。
    • 使用缓存机制。
    • 减少查询返回的字段数量。
  3. 如何处理分页参数无效的情况?

    • 使用FastAPI的Query参数验证功能。
    • 返回422 Validation Error。
    • 在API文档中明确说明参数要求。

常见报错解决方案:

  • 422 Validation Error:检查分页参数的取值范围,确保符合验证规则。
  • 500 Internal Server Error:捕获异常并返回友好的错误信息,检查数据库查询逻辑。
  • 404 Not Found:确保分页参数不会导致查询结果为空,处理边界情况。

余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长,阅读完整的文章:FastAPI 核心机制:分页参数的实现与最佳实践 | cmdragon's Blog

往期文章归档:

  • FastAPI 错误处理与自定义错误消息完全指南:构建健壮的 API 应用 🛠️ | cmdragon's Blog
  • FastAPI 自定义参数验证器完全指南:从基础到高级实战 | cmdragon's Blog
  • FastAPI 参数别名与自动文档生成完全指南:从基础到高级实战 🚀 | cmdragon's Blog
  • FastAPI Cookie 和 Header 参数完全指南:从基础到高级实战 🚀 | cmdragon's Blog
  • FastAPI 表单参数与文件上传完全指南:从基础到高级实战 🚀 | cmdragon's Blog
  • FastAPI 请求体参数与 Pydantic 模型完全指南:从基础到嵌套模型实战 🚀 | cmdragon's Blog
  • FastAPI 查询参数完全指南:从基础到高级用法 🚀 | cmdragon's Blog
  • FastAPI 路径参数完全指南:从基础到高级校验实战 🚀 | cmdragon's Blog
  • FastAPI路由专家课:微服务架构下的路由艺术与工程实践 🌐 | cmdragon's Blog
  • FastAPI路由与请求处理进阶指南:解锁企业级API开发黑科技 🔥 | cmdragon's Blog
  • FastAPI路由与请求处理全解:手把手打造用户管理系统 🔌 | cmdragon's Blog
  • FastAPI极速入门:15分钟搭建你的首个智能API(附自动文档生成)🚀 | cmdragon's Blog
  • HTTP协议与RESTful API实战手册(终章):构建企业级API的九大秘籍 🔐 | cmdragon's Blog
  • HTTP协议与RESTful API实战手册(二):用披萨店故事说透API设计奥秘 🍕 | cmdragon's Blog
  • 从零构建你的第一个RESTful API:HTTP协议与API设计超图解指南 🌐 | cmdragon's Blog
  • Python异步编程进阶指南:破解高并发系统的七重封印 | cmdragon's Blog
  • Python异步编程终极指南:用协程与事件循环重构你的高并发系统 | cmdragon's Blog
  • Python类型提示完全指南:用类型安全重构你的代码,提升10倍开发效率 | cmdragon's Blog
  • 三大平台云数据库生态服务对决 | cmdragon's Blog
  • 分布式数据库解析 | cmdragon's Blog
  • 深入解析NoSQL数据库:从文档存储到图数据库的全场景实践 | cmdragon's Blog
  • 数据库审计与智能监控:从日志分析到异常检测 | cmdragon's Blog
  • 数据库加密全解析:从传输到存储的安全实践 | cmdragon's Blog
  • 数据库安全实战:访问控制与行级权限管理 | cmdragon's Blog
  • 数据库扩展之道:分区、分片与大表优化实战 | cmdragon's Blog
  • 查询优化:提升数据库性能的实用技巧 | cmdragon's Blog
  • 性能优化与调优:全面解析数据库索引 | cmdragon's Blog
  • 存储过程与触发器:提高数据库性能与安全性的利器 | cmdragon's Blog
  • 数据操作与事务:确保数据一致性的关键 | cmdragon's Blog
  • 深入掌握 SQL 深度应用:复杂查询的艺术与技巧 | cmdragon's Blog
  • 彻底理解数据库设计原则:生命周期、约束与反范式的应用 | cmdragon's Blog
  • 深入剖析实体-关系模型(ER 图):理论与实践全解析 | cmdragon's Blog
  • 数据库范式详解:从第一范式到第五范式 | cmdragon's Blog
  • PostgreSQL:数据库迁移与版本控制 | cmdragon's Blog
  • Node.js 与 PostgreSQL 集成:深入 pg 模块的应用与实践 | cmdragon's Blog

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/897975.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

https://www.cnblogs.com/B2205/p/18768998

一、团队介绍 1.1 团队概况 1.1.1 博客展示链接 团队名:师联星 组长博客链接:https://www.cnblogs.com/nurali1508 1.1.2 团队项目描述 项目名称:师联星 定位:大学生家教辅助软件 核心功能:通过智能匹配系统连接学生与家教老师,提供个性化教学方案和课程监督服务。 1.1.3…

皮肤测试

目录Typora 主题测试文档1. 标题样式H3 标题H4 标题H5 标题H6 标题2. 文本格式3. 列表样式无序列表有序列表任务列表4. 代码块5. 表格6. 图片7. 数学公式8. 其他元素水平线引用块脚注空行代码主题 Typora 主题测试文档 1. 标题样式 H3 标题 H4 标题 H5 标题 H6 标题 2. 文本格式…

https://www.cnblogs.com/nurali1508/p/18766565

一、团队介绍 1.1 团队概况 1.1.1 博客展示链接 团队名,组长博客链接https://www.cnblogs.com/nurali1508 1.1.2 团队项目描述 师联星——方便大学生家教的辅助软件 1.1.3 队员风采 努尔艾力 风格:有趣 擅长的技术: 编程的兴趣:安静 希望的软工角色:发言和统计 一句话宣言…

如何调用CMD实现多个同类文件合并的研究 二进制 依次 文本图像视频音频

引言 视频网站内,使用视频下载嗅探器下载了视频,打开资源管理器一看,是几千个.ts文件,见下图: 通过播放部分视频,发现其实内容是完整的,只是自动切割了多份,倘若无缝拼接为一个完整视频单元,就可以正常播放观赏了。 经过考虑,可以使用视频编辑软件,比如PR,导入素材…

师联星

一、团队介绍 1.1 团队概况 1.1.1 博客展示链接 团队名,组长博客链接https://www.cnblogs.com/nurali1508 1.1.2 团队项目描述 师联星——方便大学生家教的辅助软件 1.1.3 队员风采 努尔艾力 风格:有趣 擅长的技术: 编程的兴趣:安静 希望的软工角色:发言和统计 一句话宣言…

【程设の旅】魔兽世界 Part4:终极

写完还是挺累的 主要是那个憨憨四万三千行的数据包 调的人有点晕 而且里面还有三个憨憨四舍五入 搞得人晕乎乎 最后这三个数据只能打表 唉 放代码吧 感觉类与对象封装还是不敢用 等后面自己做个QT项目练一练咯 #include<bits/stdc++.h> #define ll long long using names…

[AIGC/ALM] 增强语言模型(ALM)之综述

1 简介最近Meta发表了一篇图灵奖得主Yann LeCun参与的关于“Augmented Language Models: a Survey/增强语言模型:一篇调查”的综述,系统归纳了语言模型的推理能力以及使用外部工具能力的工作(推理指将复杂任务分解为更简单的子任务,工具包括调用模块等 ),并指出这个方向有可…

Vue3 icon使用

icon使用:https://cn.element-plus.org/zh-CN/component/icon.html 1.安装icon2.配置main.js点击查看代码 import { createApp } from vue import ElementPlus from element-plus import element-plus/dist/index.cssimport App from ./App.vue import router from ./routerim…

第一周实验:已有程序二次开发

一. 来源 代码来源于室友大一期末大作业。该程序模拟实现了一个简易的图书管理系统,功能有用户注册登录,查询,购买书籍,管理员对书籍的增删改查功能。 二.程序原来的代码及运行结果 运行环境:Windows 11 + Visual Studio 2022点击查看代码 #include<iostream> #incl…

知识点系列——基础数据结构

1.1 链表 洛谷-P1996 约瑟夫问题我就直接模拟void solve() {cin>>n>>k;int id=0;for(int i=1;i<=n;i++){int p=0;while(p<k){bool f=false;while(vis[id]){id++;f=1;if(id>n)id=1;}if(!f){id++;if(id>n)id=1;while(vis[id]){id++;if(id>n)id=1;}}p+…

Laravel11 从0开发 Swoole-Reverb 扩展包(七) - 发布laravel-swoole-reverb

开篇 这一篇,我做了过度,因为正好也完成第一个版本的laravel swoole reverb服务。因此,先做个🧐,我们后面还会继续分享整个实现流程。 关于laravel-swoole-reverb laravel-swoole-reverb是一个将 Swoole 与 Laravel Reverb 集成的包,采用php8.2版本编写,可用于高性能的…

TinyWebServer全解

项目地址 原理合集 把链接都放在这里,可以一次看个爽 epoll main 首先是main函数: #include "config.h"int main(int argc, char *argv[]) {//需要修改的数据库信息,登录名,密码,库名string user = "ct";string passwd = "123456";string data…