07. FastAPI 请求参数类型验证_Query方式
Query 管查询参数的规则
类型回答“它是什么”,Query 补充“从查询串取,并满足什么规则”。推荐用 Annotated 把类型与参数说明放在一起,默认值放在 = 后,写法更清楚。
python
from typing import Annotated, Literal
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/products")
def products(
keyword: Annotated[str | None, Query(min_length=2, max_length=30)] = None,
page: Annotated[int, Query(ge=1)] = 1,
size: Annotated[int, Query(ge=1, le=100)] = 20,
sort: Literal["id", "price"] = "id",
tags: Annotated[list[str] | None, Query()] = None,
):
return {"keyword": keyword, "page": page, "size": size,
"sort": sort, "tags": tags or []}保存为 main.py,启动 uv run uvicorn main:app --reload。调用 /products?keyword=键盘&page=2&size=10&tags=数码&tags=办公,应得到第二页、每页 10 条以及两个标签。page=0、size=101、sort=random 都会得到 422。
常用规则速查
| 参数 | 作用 | 例子 |
|---|---|---|
min_length、max_length | 字符串长度 | 搜索词 2~30 字符 |
gt、ge | 大于、大于等于 | ge=1 |
lt、le | 小于、小于等于 | le=100 |
pattern | 正则约束 | pattern=r"^[a-z0-9_-]+$" |
alias | 对外参数名称 | alias="page-size" |
description | 文档说明 | 是否包含停用商品 |
deprecated | 标记弃用 | 提示客户端迁移 |
想约束整个字符串时,正则应根据需求加起止锚点。列表参数一般用重复键,不要误认为 tags=a,b 一定会自动分成两个元素。
必填与别名示例
以下是独立的补充路由,可以追加到前面的程序中:
python
@app.get("/search")
def search(
q: Annotated[str, Query(min_length=1, description="搜索词")],
page_size: Annotated[int, Query(alias="page-size", ge=1, le=50)] = 10,
):
return {"q": q, "page_size": page_size}调用 /search?q=python&page-size=5。没有默认值的 q 必填;对外用 page-size,Python 里仍用合法变量名 page_size。
进一步思考
查询条件多时可以组织成查询参数模型,但需核对所用 FastAPI 版本支持情况。不要把所有条件都设为任意字符串后拼接 SQL;排序字段应使用白名单映射到模型列。
练习:加入 min_price 和 max_price,先限制各自非负,再在业务逻辑中检查最小值不大于最大值。单字段规则和跨字段规则应分别处理。