FastAPI教程-路径参数-Annotated参数校验(新版,替代Path)

旧版写法

@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存放校验元数据,旧写法属于兼容遗留模式。

例子:重新实现上面的校验

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函数内部:
    # 查询参数可选,默认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