Skip to content

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,先限制各自非负,再在业务逻辑中检查最小值不大于最大值。单字段规则和跨字段规则应分别处理。