首页 / FastAPI 入门教程 / 路径参数校验

FastAPI 入门教程

路径参数校验

本教程共 50 篇 · 第 7 篇 · 更新于 2026-08-12 · 约 7 分钟阅读

FastAPIFastAPI 入门教程路径参数校验PathEnum数值范围

本节目标:学会用 Path() 给路径参数加范围约束,用 Enum 限制只能是几个固定值,用 :path 让参数能装下整条子路径,并把约束自由组合。

上一章我们知道,给路径参数写一个类型(比如 int)就能自动校验。但很多时候要求更高:id 必须大于 0、颜色只能是红绿蓝之一、文件路径要带斜杠。这一章就讲这些更细的约束。

7-1 用 Path 声明约束

要给路径参数加额外规则,需要用到 Path,并配合 Annotated 写进类型注解里。先看一个限制「最小值」的例子:

from typing import Annotated
from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(
    item_id: Annotated[int, Path(title="要查询的商品 ID", ge=1)]
):
    return {"item_id": item_id}

这里 Path(ge=1) 表示 item_id 必须是一个整数,且「大于等于 1」(ge = greater than or equal)。访问 /items/0 会直接报错,因为 0 不满足 ge=1;访问 /items/5 则正常。

Note

路径参数天生就是必填的——它写在 URL 里,不能省略。所以 Path 不需要也不支持把它设成可选,哪怕你写了默认值也会被忽略。

7-2 四个数值范围约束

数字类型的路径参数,常用这四种约束:

写法含义中文
gtgreater than大于
gegreater than or equal大于等于
ltless than小于
leless than or equal小于等于

把它们组合一下,限定 id 落在 1 到 1000 之间:

from typing import Annotated
from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(
    item_id: Annotated[int, Path(title="商品 ID", gt=0, le=1000)]
):
    return {"item_id": item_id}

gt=0 表示必须严格大于 0,le=1000 表示最多到 1000。传 0-51001 都会被拦下。

7-3 约束对浮点数同样有效

这些范围约束对 float 一样好使。浮点数场景下 gtlt 特别有用,因为它能表达「大于 0 但小于 1」这种区间,比如 0.5 合法,而 0.0 不合法:

from typing import Annotated
from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}/sizes/{size}")
async def read_item(
    item_id: Annotated[int, Path(title="商品 ID", ge=0, le=1000)],
    size: Annotated[float, Path(title="尺寸", gt=0, lt=10.5)],
):
    return {"item_id": item_id, "size": size}

访问 /items/3/sizes/5.5 会正常返回 {"item_id": 3, "size": 5.5};访问 /items/3/sizes/11 则返回 422,因为 11 不满足 lt=10.5。浮点约束常出现在分页大小、金额等场景。

7-4 用 Enum 限定只能是固定值

如果路径参数只能取几个确定的值,比如模型名字只能是 alexnetresnetlenet,就用 Python 的 Enum。注意让它同时继承 strEnum

from enum import Enum
from fastapi import FastAPI

app = FastAPI()


class ModelName(str, Enum):
    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"


@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
    return {"model_name": model_name}

继承 str 的好处是:文档能正确识别这些值是字符串,渲染更友好;而且你直接用 model_name.value 就能拿到字符串本身。访问 /models/alexnet 返回 {"model_name": "alexnet"};访问 /models/foobar 会报错,提示合法值只有三个。

在函数内部,model_name 是一个枚举成员,可以拿它和枚举类比较:

@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
    if model_name is ModelName.alexnet:
        return {"model_name": model_name, "message": "选了 AlexNet"}
    return {"model_name": model_name}

要拿真正的字符串值,用 model_name.value;要拿枚举成员本身,直接返回 model_name 也行,FastAPI 会自动转成对应的字符串再回给客户端。

7-5 用 :path 匹配含斜杠的路径

有时路径参数自身就包含斜杠,比如文件路径 /home/johndoe/myfile.txt。普通路径参数遇到第一个斜杠就截断了,所以要用 Starlette 的路径转换器 :path

from fastapi import FastAPI

app = FastAPI()


@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
    return {"file_path": file_path}

注意写法是在花括号里写成 {file_path:path},冒号后面的 path 告诉 FastAPI 这个参数要匹配「一整条路径」。访问 http://127.0.0.1:8000/files/home/johndoe/myfile.txt,返回:

{"file_path": "home/johndoe/myfile.txt"}
Tip

如果你的路径以斜杠开头,比如想匹配 /home/...,那 URL 要写成 /files//home/...fileshome 之间会出现两个斜杠 //。这是正常的,第一个斜杠是路由分隔,第二个才是参数内容的一部分。

7-6 把约束组合在一起

Path 的约束可以一次写多个,也能和 Enum、类型一起用。下面这个例子同时限制了 id 的范围,并给参数加了文档标题:

from typing import Annotated
from enum import Enum
from fastapi import FastAPI, Path

app = FastAPI()


class Level(str, Enum):
    low = "low"
    high = "high"


@app.get("/tasks/{task_id}/{level}")
async def read_task(
    task_id: Annotated[int, Path(title="任务 ID", ge=1, le=999)],
    level: Level,
):
    return {"task_id": task_id, "level": level}

这里 task_id 必须是整数且 1 到 999,level 只能是 lowhigh。多个约束写在一个 Path(...) 里就行,互不冲突。

约束不通过时,FastAPI 会返回状态码 422,响应体里带上出错字段的位置和原因,你不需要自己写任何判断语句。这一点很关键:校验发生在你的函数被调用之前,所以函数体里拿到的值一定已经满足全部约束,可以放心直接使用,不必再补一层防御性检查。

Note

QueryPath 以及后面会学到的 BodyHeaderCookie 都继承自同一个 Param 类,所以它们支持的约束参数几乎一样。学会一个,其余触类旁通。

7-7 参数顺序不必纠结

使用 Annotated 之后,函数里参数的前后顺序已经无所谓了。FastAPI 按「名字、类型、默认值声明」来认参数,不关心你把它写在第几位。早期没有 Annotated 时,如果你既用了 Path 又想放一个没有默认值的普通参数,顺序写错 Python 会报错,那时要用 * 把后面的参数都变成关键字参数来化解。

现在我们用 Annotated 写法,这个麻烦基本碰不到,知道有这回事即可。建议新项目统一用 Annotated 风格,代码更清晰,也更不容易踩顺序的坑。

7-8 小结

这一章给路径参数上了「紧箍咒」:Path(ge=1, le=1000)gt/ge/lt/le 限制数值范围,对整数和浮点数都有效;Enum 让参数只能取你定义的几个固定值,文档里还会直接列出可选项;{file_path:path} 让参数能吞下整条带斜杠的子路径;这些约束还能任意组合。

下一章我们转向「查询参数」,看看 URL 里 ? 后面那些键值对怎么玩。