跳到主要内容

参数校验

前言

FastAPI 支持对路径参数、查询参数、表单参数、请求体参数声明校验规则。校验器分为两类:

  • Query / Path / Form / Body / Header / Cookie:FastAPI 提供的参数声明类,同时标注参数来源。
  • Field:Pydantic 的字段校验类,用在请求体模型中。

两者用法相似:参数名: 类型 = Query(默认值或..., 校验参数...)

备注

...(Ellipsis)表示参数为必填;如果不想用 ...,也可以不写默认值(无默认值即为必填),或者用 Annotated 写法(推荐,见下文)。

查询参数基础

from fastapi import FastAPI

app = FastAPI()


# 给了默认值就是选填参数
# 设置为 None 便是可选参数
@app.get("/query")
def page_limit(page: int = 1, limit: int | None = None):
if limit:
return {"page": page, "limit": limit}
return {"page": page}

布尔类型转换

# yes, true, on, 1 等都会被转换成 True
@app.get("/query/bool/conversion")
def type_conversion(param: bool = False):
return param

查询参数校验:Query

Query 显式声明查询参数,并支持长度、正则、范围等校验:

from fastapi import Query


@app.get("/query/validate")
def get_query_validate(
# ... 表示参数为必需
# 字符串最小 8 位,最长 16 位,以 a 开头
value: str = Query(..., min_length=8, max_length=16, pattern=r"^a"),
# alias 表示可以用 alias_name 作为参数名来传递参数
values: list[str] = Query(default=["v1", "v2"], alias="alias_name"),
):
return value, values

测试:

curl -X 'GET' \
'http://127.0.0.1:8000/query/validate?value=a12345678&alias_name=v123&alias_name=v234' \
-H 'accept: application/json'
备注

旧版本参数名为 regex,pydantic v2 / 新版 FastAPI 统一为 pattern,二者等价。

路径参数校验:Path

from fastapi import Path


@router.get("/pay/{uid}/{item_id}")
async def read_user_item(
uid: int = Path(..., title="user id", description="user id info", ge=1000),
item_id: str = Path(
..., title="item id", description="item id info", min_length=10, max_length=100
),
):
return {"uid": uid, "item_id": item_id}
参数说明
...表示此参数为必填项;改为 default=None 即为非必填
title显示在 OpenAPI 中的参数名称
ge / le整型参数范围校验:大于等于 / 小于等于
gt / lt整型参数范围校验:大于 / 小于
min_length / max_length字符串参数长度校验
pattern字符串正则校验
注意

路径参数即使写了默认值也是必填的(URL 里必须有该段)。

查询参数范围校验

from fastapi import Query


@router.get("/item")
async def test2(
page: int = Query(default=0, title="页数", ge=0, le=100),
offset: int = Query(default=0, title="偏移量", ge=0, le=100),
):
return {"page": page, "offset": offset}

表单参数校验:Form

from fastapi import Form


@router.post("/form", summary="处理表单请求参数")
def formtest1(
username: str = Form(..., min_length=6, max_length=12),
password: str = Form(..., min_length=6, max_length=12),
):
return {"username": username, "password": password}

请求体参数校验:Body 与 Field

可以用 Body 对单个请求体字段做校验,也可以用 Pydantic 的 Field 在模型中声明校验规则:

from pydantic import BaseModel, Field


class ReqBody6(BaseModel):
user_id: int = Field(..., title="用户id", gt=10000, lt=100000)
user_name: str | None = Field(default=None, title="用户名", max_length=20)


@router.post("/body", response_model=ReqBody6, response_model_exclude={"user_name"})
async def test4(req: ReqBody6):
return req
提示

response_model_exclude 接收 set[str](或 dict),response_model_exclude={"user_name"}。更多响应模型用法见 响应报文

HeaderCookie 用法与 Query 一致,示例见 解析请求

Annotated 写法(推荐)

新版 FastAPI 推荐用 Annotated 把参数声明和类型放一起,避免默认值带来的函数签名污染:

from typing import Annotated

from fastapi import Query


@router.get("/annotated")
async def annotated(
q: Annotated[str | None, Query(max_length=10)] = None,
page: Annotated[int, Query(ge=1)] = 1,
):
return {"q": q, "page": page}
提示

Annotated 是社区推荐的写法;Query(...) 作为默认值的写法仍然兼容,笔记中两种都保留了。