反思 · 2026年6月20日

昨天和今天把 FastAPI 的参数校验体系(PathQueryField)过了一遍。刚开始觉得这三个东西长得太像,都是用来加校验的,容易记混。但理清它们的应用场景之后,发现逻辑异常清晰。

核心结论先行:

QueryPath 是写给 URL 的(函数参数),**Field** 是写给 JSON 请求体 的(Pydantic 模型属性)。


1. Query:处理 URL 的 “问号” 部分

一句话定义:处理 /items?page=1&size=10 这种键值对。

关键特性:在函数参数中,如果不写 PathBody,FastAPI 默认就把它当成 Query。也就是说,它是默认选项

为什么显式使用 Query? 主要是为了增加校验规则(比如限制数值范围、正则匹配)。

1
2
3
4
5
6
7
8
9
10
11
12
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items")
def list_items(
# ... 表示必填,ge=1 表示必须大于等于 1
page: int = Query(..., ge=1, title="页码"),
# 默认值是 10,le=100 限制最大值为 100
size: int = Query(10, le=100, description="每页数量")
):
return {"page": page, "size": size}

2. Path:处理 URL 的 “路径” 部分

一句话定义:处理 /users/{user_id} 这种动态路由。

关键特性:只要函数参数名和路径变量名一致,FastAPI 会自动识别。但必须显式加上 Path 才能添加校验

特别注意:路径参数永远不可能为空(URL 少了它直接 404),所以第一个参数永远是 ...(Required)。

1
2
3
4
5
6
7
8
9
10
from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/users/{user_id}")
def get_user(
# gt=0 确保 ID 为正整数
user_id: int = Path(..., gt=0, title="用户ID")
):
return {"user_id": user_id}

3. Field:处理请求体(JSON Body)的内部字段

一句话定义:定义 Pydantic 模型中字段的校验规则。

关键特性:它不直接面对 URL,而是定义在 BaseModel 的类属性里。通常用于 POST / PUT 请求接收 JSON 数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
from pydantic import BaseModel, Field

class CreateItem(BaseModel):
# 必填,长度限制 2~50
name: str = Field(..., min_length=2, max_length=50, description="物品名称")
# 必填,价格在 0~9999 之间
price: float = Field(..., gt=0, le=9999, example=19.99)
# 选填,如果不传默认空字符串
description: str = Field("", max_length=200)

@app.post("/items")
def create_item(item: CreateItem): # 框架自动识别为请求体 JSON
return item

4. 一图看懂三者的本质区别(核心)

工具 作用位置 数据来源示例 是否必须显式声明
Query 函数参数 ?key=value 否(默认就是它),声明是为了加校验
Path 函数参数 /users/{id} 否(框架能推断),声明是为了加校验
Field Pydantic 类属性 {"key": "value"} (Body) (因为类属性无法自动识别为字段校验)

5. 开发中的“避坑”

  1. 关于必填与选填

    • QueryPath... 表示必填,用 None 或默认值表示选填。
    • Field 同样遵循此规则,但 Field(...) 指的是 JSON 中必须存在该字段。
  2. 参数别名(Alias)

    • 如果前端传参是 user-id(带横杠),Python 变量不能用横杠,就用 Path(..., alias="user-id")Query(..., alias="user-id") 完美解决。
  3. 关于 ... 的冷知识

    • ... 是 Python 的 Ellipsis(省略号)字面量,FastAPI 用它来区分“未设置默认值”和“默认值为 None”。记住:看到 ... 就代表前端必须给
  4. 不要混用场景

    • GET 请求不要用 Field(它不会被解析),POST 请求不要用 Query 传复杂对象(应该用 Body)。

6. 今日小结

FastAPI 的设计哲学是显式优于隐式。虽然它能自动推断参数来源,但作为开发者,明确写出 QueryPath 或使用 Field,不仅能让代码意图清晰,还能充分利用 Pydantic 的校验能力,规避后期维护的坑。


本站由 Esters 使用 Stellar 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。