反思 · 2026年6月20日
昨天和今天把 FastAPI 的参数校验体系(Path、Query、Field)过了一遍。刚开始觉得这三个东西长得太像,都是用来加校验的,容易记混。但理清它们的应用场景之后,发现逻辑异常清晰。
核心结论先行:
Query和Path是写给 URL 的(函数参数),**Field** 是写给 JSON 请求体 的(Pydantic 模型属性)。
1. Query:处理 URL 的 “问号” 部分
一句话定义:处理 /items?page=1&size=10 这种键值对。
关键特性:在函数参数中,如果不写 Path 或 Body,FastAPI 默认就把它当成 Query。也就是说,它是默认选项。
为什么显式使用 Query? 主要是为了增加校验规则(比如限制数值范围、正则匹配)。
1 | from fastapi import FastAPI, Query |
2. Path:处理 URL 的 “路径” 部分
一句话定义:处理 /users/{user_id} 这种动态路由。
关键特性:只要函数参数名和路径变量名一致,FastAPI 会自动识别。但必须显式加上 Path 才能添加校验。
特别注意:路径参数永远不可能为空(URL 少了它直接 404),所以第一个参数永远是 ...(Required)。
1 | from fastapi import FastAPI, Path |
3. Field:处理请求体(JSON Body)的内部字段
一句话定义:定义 Pydantic 模型中字段的校验规则。
关键特性:它不直接面对 URL,而是定义在 BaseModel 的类属性里。通常用于 POST / PUT 请求接收 JSON 数据。
1 | from pydantic import BaseModel, Field |
4. 一图看懂三者的本质区别(核心)
| 工具 | 作用位置 | 数据来源示例 | 是否必须显式声明 |
|---|---|---|---|
| Query | 函数参数 | ?key=value |
否(默认就是它),声明是为了加校验 |
| Path | 函数参数 | /users/{id} |
否(框架能推断),声明是为了加校验 |
| Field | Pydantic 类属性 | {"key": "value"} (Body) |
是(因为类属性无法自动识别为字段校验) |
5. 开发中的“避坑”
关于必填与选填:
Query和Path用...表示必填,用None或默认值表示选填。Field同样遵循此规则,但Field(...)指的是 JSON 中必须存在该字段。
参数别名(Alias):
- 如果前端传参是
user-id(带横杠),Python 变量不能用横杠,就用Path(..., alias="user-id")或Query(..., alias="user-id")完美解决。
- 如果前端传参是
关于
...的冷知识:...是 Python 的Ellipsis(省略号)字面量,FastAPI 用它来区分“未设置默认值”和“默认值为 None”。记住:看到...就代表前端必须给。
不要混用场景:
- GET 请求不要用
Field(它不会被解析),POST 请求不要用Query传复杂对象(应该用 Body)。
- GET 请求不要用
6. 今日小结
FastAPI 的设计哲学是显式优于隐式。虽然它能自动推断参数来源,但作为开发者,明确写出 Query、Path 或使用 Field,不仅能让代码意图清晰,还能充分利用 Pydantic 的校验能力,规避后期维护的坑。