FastAPI 查询参数约束实战:分页、过滤与参数校验
在 FastAPI 开发中,URL 查询参数(Query Parameter)非常常见,例如 ?name=xxx&class_id=1&skip=0&limit=10。如果不加约束,用户可能传入非法值(如 limit=-1),导致接口行为异常。本文将基于 FastAPI 的 Query 与 Pydantic 的 Annotated,为查询参数加上类型、范围与描述约束,并实现按姓名模糊查询、按班级过滤以及分页效果。
一、目标
以“查询所有学生列表”接口为例,实现以下查询参数:
name:学生姓名模糊查询,字符串类型;class_id:班级 ID,整数,且必须>= 1;skip:跳过前面 n 条记录,整数,>= 0,默认 0;limit:每页最多返回 n 条记录,整数,范围1 ~ 100,默认 10。
最终效果:接口文档中自动展示参数说明与校验规则,非法参数会被自动拦截并返回精确错误信息。
二、代码实现
1. 导入依赖
使用 Annotated 为参数附加元数据,使用 FastAPI 的 Query 声明查询参数约束:
from typing import Annotated
from fastapi import Query
2. 为查询参数添加约束
在路由函数中定义四个参数,并通过 Annotated + Query 设置描述、范围与默认值:
@app.get("/api/v1/students", response_model=ApiResponse[list[Student]],tags=["学生管理"])
def get_students(
name: Annotated[str | None, Query(description="学生信息,模糊查询") ] = None,
class_id: Annotated[int | None, Query(ge=1,description="班级ID") ] = None,
skip: Annotated[int, Query(ge=0, description="跳过前面N条记录,用于分页")] = 0,
limit: Annotated[int, Query(ge=1, le=100, description="最多返回N条件记录")] = 10
):
...
要点说明:
description会显示在接口文档中;ge表示大于等于,le表示小于等于;limit限制在 1~100,避免一次查询过多数据导致查询变慢。
3. 处理查询逻辑
先拿到完整数据,再依次按 name、class_id 过滤,最后做分页切片:
results = get_all_students() # 完整数据
if name:
results = [s for s in results if name in s.name]
if class_id is not None:
results = [s for s in results if s.get("class_id") == class_id]
pagination = results[skip: skip + limit]
return pagination
分页原理:skip 为 0、limit 为 10 时显示第一页 10 条;要显示第二页,则 skip=10、limit=10,即跳过前 10 条,从第 11 条开始再取 10 条。
4. 优化:提前触发模型校验
上面返回的是原始字典,校验发生在返回之后。更推荐在函数内就把每条记录组织成 Pydantic 定义的 Student 模型,让校验更早触发,出问题更方便定位:
students = [Student(**s) for s in pagination]
return students
三、测试验证
打开接口文档,可以看到新增的 name、class_id、skip、limit 四个查询参数及其说明。
1. 默认查询
不填任何参数直接执行,返回所有学生数据。
2. 姓名模糊查询
在 name 中输入关键字(如“里”),执行后只返回姓名包含该关键字的记录(如 ID 为 2 的“里纳”)。
3. 班级 ID 校验
输入 class_id=1 查询,返回两条该班级记录;输入 class_id=2,返回一条记录。若输入不满足 >= 1 的值,接口会直接提示参数需大于等于 1 的错误信息。
4. 分页效果
共三条记录,设置 skip=1、limit=1,返回跳过第一条后的那一条记录;设置 skip=1、limit=2,则返回两条记录,分页效果生效。
5. 范围校验
将 limit 设为 -1,接口提示至少需大于等于 1;将 skip 设为不合法值同样会被拦截,说明约束规则已生效。
6. 联合查询
同时设置 class_id 与 name 条件进行组合过滤,结果符合预期;优化后的模型校验版本测试结果与之前一致。
四、校验流程回顾
- 客户端发送请求数据;
- 触发字段格式约束(
Field固定约束,如最大值、最小值); - 需要自定义单字段规则时使用
field_validator; - 需要跨字段规则验证时使用
model_validator; - 校验通过后提交路由函数处理;
- 以上任何一步失败都会自动返回 4xx 及精确错误信息,路由函数再决定是否执行后续内容。
五、小结
本节重点:
- 使用
Field做长度、正则、数值范围约束; - 可选枚举类型(如性别只有男/女)使用
Literal做枚举约束; - 单字段校验用
field_validator,多字段校验用model_validator; - 查询参数校验使用
Annotated类型 +Query,配合ge、le与description实现范围约束与文档说明。
至此,Pydantic 数据校验相关内容介绍完毕。
想系统学习这门课程?
你已阅读完本文。需要更完整的知识体系,可以继续了解「FastAPI 项目实战」。
查看课程详情