FastAPI 路径参数
路径参数是 URL 路径中的动态部分,使用花括号 {} 声明。FastAPI 会自动将路径参数传递给路径操作函数,并根据类型注解进行数据转换和校验。
基本用法
使用 Python 格式化字符串的语法声明路径参数:
实例
app = FastAPI()
# {item_id} 是路径参数
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
访问 http://127.0.0.1:8000/items/5,返回:
{"item_id": 5}
注意返回的 item_id 是整数 5,不是字符串 "5"。FastAPI 通过类型注解 item_id: int 自动将 URL 中的字符串转换为整数。
数据转换
当你声明类型为 int 时,FastAPI 会自动进行类型转换:
# 传入整数,正常工作
GET /items/3 -> {"item_id": 3}
# 传入非整数,返回校验错误
GET /items/foo -> 错误:Input should be a valid integer
# 传入浮点数,同样报错
GET /items/4.2 -> 错误:Input should be a valid integer
访问 http://127.0.0.1:8000/items/foo 时,FastAPI 返回的校验错误信息:
{
"detail": [
{
"type": "int_parsing",
"loc": ["path", "item_id"],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "foo"
}
]
}
FastAPI 的校验错误信息非常清晰,会指出具体的错误位置(
loc)、错误类型(type)和错误描述(msg)。这在调试时非常有用。
路径参数的类型
除了 int,你还可以使用其他标准 Python 类型:
| 类型 | 说明 | URL 示例 |
|---|---|---|
str | 字符串(默认类型) | /items/foo |
int | 整数 | /items/5 |
float | 浮点数 | /items/5.5 |
bool | 布尔值 | /items/true |
uuid.UUID | UUID | /items/3fa85f64-5717-4562-b3fc-2c963f66afa6 |
路径顺序很重要
当多个路由可能匹配同一个 URL 时,定义的顺序决定了匹配结果。FastAPI 按照路由定义的顺序依次匹配,第一个匹配的路由将被执行。
实例
app = FastAPI()
# 必须在 /users/{user_id} 之前定义
@app.get("/users/me")
async def read_user_me():
"""获取当前用户信息"""
return {"user_id": "the current user"}
@app.get("/users/{user_id}")
async def read_user(user_id: str):
"""根据 ID 获取用户信息"""
return {"user_id": user_id}
如果把 /users/me 放在 /users/{user_id} 之后,那么访问 /users/me 时,FastAPI 会认为 "me" 是 user_id 的值,从而匹配到错误的函数。
固定路径的路由一定要放在动态路径参数的路由之前,否则动态参数会把固定路径的值"吞掉"。
预设值的路径参数(Enum)
当你需要限制路径参数只能是几个固定值时,可以使用 Python 的 Enum 类型:
实例
from fastapi import FastAPI
# 创建枚举类,继承 str 和 Enum
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
# 可以与枚举成员比较
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
枚举类的要点:
| 要点 | 说明 |
|---|---|
继承 str | 让 API 文档将值类型识别为字符串,确保正确渲染 |
继承 Enum | 创建枚举类型,限制可选值 |
model_name.value | 获取枚举成员的实际值(如 "alexnet") |
访问 http://127.0.0.1:8000/models/alexnet,返回:
{"model_name": "alexnet", "message": "Deep Learning FTW!"}
如果传入非预设值(如 /models/foobar),FastAPI 会返回校验错误,提示可选值为 alexnet、resnet、lenet。
包含路径的路径参数
当你需要路径参数本身包含路径(如文件路径)时,使用 Starlette 的路径转换器:
实例
app = FastAPI()
# :path 表示该参数可以匹配包含斜杠的路径
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
return {"file_path": file_path}
访问 http://127.0.0.1:8000/files/home/johndoe/myfile.txt,返回:
{"file_path": "home/johndoe/myfile.txt"}
注意 URL 中
/files/和/home/之间会出现双斜杠//,这是正常的,因为路径参数以/开头。
小结
通过 Python 标准的类型声明,FastAPI 路径参数可以同时获得:
- 数据转换:URL 中的字符串自动转为声明的类型
- 数据校验:类型不匹配时返回清晰的错误信息
- 自动文档:路径参数的类型和约束自动出现在 API 文档中
- 编辑器支持:类型注解让你在编辑器中获得自动补全
