FastAPI教程-路径参数-Annotated参数校验(新版,替代Path) 作者:马育民 • 2026-08-13 11:07 • 阅读:10001 # 旧版写法 ```python @app.get('/student/{age}') async def get_student(age: int=Path(...,ge=10,le=120,description="年龄大于等于10岁,小于等于120岁")): return {'msg': f'年龄{age}'} ... ``` ### 缺点 1. **`...`(Ellipsis省略号)极易遗忘** - 路径参数必须写`Path(..., ge=1)` - 漏写`...`写成`Path(ge=1)`,会把`ge=1`当作default默认值,直接运行时异常,坑非常多。 2. **类型注解与元数据耦合在一起** - 真正的类型 `int` 和校验元数据`Path()`被`=`赋值绑定。 - 阅读代码时,要跳到等号右边才能看到校验规则。 3. **类型提示工具容易乱** IDE/mypy 有时候推断类型出错;`Path(...)`返回的是Param对象,靠FastAPI内部做剥离。 4. **无法复用类型定义**,每处都复制粘贴一长串,重复代码,修改要改多处。 5. `Path()` 底层使用 **Pydantic v2**,与其新设计理念不一致。Pydantic v2大量使用Annotated存放校验元数据,旧写法属于兼容遗留模式。 # 例子:重新实现上面的校验 ```python from fastapi import FastAPI,Path from typing_extensions import Annotated app = FastAPI() @app.get('/student/{age}') async def get_student(age: Annotated[int,Path(ge=10,le=120,description="年龄大于等于10岁,小于等于120岁")]): return {'msg': f'年龄{age}'} ... ``` # 例子:可以复用 定义全局公共类型,多处接口复用,如下: ``` StudentName = Annotated[str,Path(min_length=2,max_length=3,description="姓名数量在2-3之间")] ``` ### 代码 ``` from fastapi import FastAPI,Path from typing_extensions import Annotated app = FastAPI() # 定义校验,可以复用 StudentName = Annotated[str,Path(min_length=2,max_length=3,description="姓名数量在2-3之间")] @app.get('/student/{name}') async def get_student(name: StudentName): """根据姓名获取学生信息""" return { 'name': name, 'age': 21, } @app.get('/score/{name}') async def get_score(name: StudentName): """根据姓名获取分数信息""" return { 'name': name, '数学': 88, } ``` # 优点 1. **彻底干掉 `...` 省略号** Path内部**不再接收default位置参数**;路径参数天然必填,不用再写`...`,减少低级错误。 2. **类型与校验元数据分离** `Annotated[真实类型, 元数据(Path/Query/Field)]` 一眼看到基础类型,后面是校验规则,代码可读性高。 3. **支持类型别名复用(企业项目最大收益)** 把一套“类型+校验”抽成类型别名,多处直接引用;修改只改一处。 4. IDE、mypy静态类型检查更稳定 真正的业务类型写在第一个位置,工具识别更准确。 5. **统一编码范式** 和Pydantic v2 `Annotated+Field`、Query、Header、Cookie语法完全统一。 - Path:`Annotated[int, Path(ge=1)]` - Query:`Annotated[int, Query(ge=1)] = None` - Body字段:`Annotated[int, Field(ge=1)]` 整套项目一套写法,记忆负担小。 6. 默认值语义清晰 查询参数的默认值写在函数参数的等号后面,不再塞到Query/Path函数内部: ```python # 查询参数可选,默认None q: Annotated[str, Query(max_length=20)] = None ``` ### 新版缺点 1. 需要导入`Annotated`(python3.9+标准库;低版本需要typing_extensions) 2. 老教程、老项目大部分是旧写法,网上复制代码容易两种写法混用,造成混乱。 # 对比 |对比项|旧版 `= Path(..., **kwargs)`|新版 `Annotated[T, Path(**kwargs)]`| |---|---|---| |必填标记|必须写`...`,极易漏写|不需要`...`| |default位置|Path第一个位置参数|default写在函数参数`=`后面| |类型可读性|类型和元数据分离在等号两边|基础类型放在最前面,一目了然| |类型别名复用|不支持,只能复制粘贴|✅支持抽别名,全局复用| |静态类型检查|偶尔IDE推断异常|IDE/mypy表现稳定| |范式统一|和Field写法不一致|与Query/Header/Field完全统一| |学习成本|要记忆`...`含义|需要理解Annotated概念| |适用场景|老项目兼容|**新项目、企业开发推荐**| # 企业开发建议 1. 新项目全部使用 **Annotated**; 2. 老项目维护:可以继续旧写法,但务必注意`Path(...,)`的三个点; 3. 公共参数(学号、id、编码等)抽成`Annotated`类型别名,多处接口直接引用。 > 补充:Annotated只是语法糖,运行时性能无差别,全部还是交给Pydantic做校验。 原文出处:/show_1GW3r0TwSP7X.html