在 FastAPI 中,路径参数(Path Parameters) 是 URL 路径的一部分,用于捕获动态的值。FastAPI 会利用 Python 的类型提示(Type Hints)自动对这些参数进行解析、类型转换和数据验证。
以下是 FastAPI 路径参数的核心用法和进阶技巧:
1. 基本用法
使用花括号 {} 在路径中声明参数,并在函数中定义同名参数。
from fastapi import FastAPI
app = FastAPI()
# 路径中声明 {item_id}
@app.get("/items/{item_id}")
async def read_item(item_id: str):
return {"item_id": item_id}访问 http://127.0.0.1:8000/items/foo,将返回 {"item_id": "foo"}。
2. 类型转换与自动验证
FastAPI 会根据你提供的类型提示自动转换数据类型。如果转换失败(例如传入了字母而不是数字),它会自动返回清晰的 HTTP 422 Unprocessable Entity 错误。
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id, "type": type(item_id).__name__}- 访问
/items/3:返回{"item_id": 3, "type": "int"} - 访问
/items/foo:返回 422 错误,提示value is not a valid integer。
3. 预定义值(使用 Enum)
如果你希望路径参数只能是几个特定的值,可以使用 Python 的 Enum 类。
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):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
# 可以通过 .value 获取字符串值
return {"model_name": model_name.value, "message": "Have some residuals"}访问 /models/resnet 会正常响应,但访问 /models/vgg 会返回 422 错误,因为 vgg 不在允许的枚举值中。
4. 包含路径的路径参数 (Path containing paths)
如果你的路径参数本身包含斜杠 /(例如文件路径),你需要使用特殊的语法 {param_name:path},并在函数参数中使用 Path。
from fastapi import FastAPI, Path
app = FastAPI()
# 注意 {file_path:path} 的写法
@app.get("/files/{file_path:path}")
async def read_file(file_path: str = Path(..., description="The file path to read")):
return {"file_path": file_path}访问 /files/home/johndoe/myfile.txt,file_path 的值将是 home/johndoe/myfile.txt。
5. 使用 Path 添加额外验证
你可以从 fastapi 导入 Path,为路径参数添加更复杂的验证规则(如最小值、最大值、正则表达式等)。... (Ellipsis) 表示该参数是必需的。
from fastapi import FastAPI, Path
from typing import Annotated # Python 3.9+ 推荐使用 Annotated
app = FastAPI()
# 传统写法
@app.get("/items/{item_id}")
async def read_item(
item_id: int = Path(..., title="The ID of the item to get", ge=1, le=1000)
):
return {"item_id": item_id}
# 现代写法 (推荐,Python 3.9+)
@app.get("/items/{item_id}")
async def read_item_modern(
item_id: Annotated[int, Path(title="The ID of the item to get", ge=1, le=1000)]
):
return {"item_id": item_id}ge=1:大于或等于 1 (greater than or equal)le=1000:小于或等于 1000 (less than or equal)- 如果传入
0或1001,将返回 422 验证错误。
6. 路径参数与查询参数混合使用
FastAPI 可以无缝区分路径参数和查询参数。路径参数在 {} 中声明,查询参数作为普通的函数参数声明。
@app.get("/users/{user_id}/items")
async def read_user_items(
user_id: int,
skip: int = 0,
limit: int = 10
):
return {
"user_id": user_id,
"skip": skip,
"limit": limit
}访问 /users/5/items?skip=20&limit=5:
user_id(路径参数) = 5skip(查询参数) = 20limit(查询参数) = 5
💡 最佳实践总结
- 始终使用类型提示:这能让 FastAPI 提供自动的数据验证和出色的 OpenAPI (Swagger) 文档。
- 优先使用
Annotated:在现代 Python (3.9+) 中,使用Annotated[type, Path(...)]是官方推荐的做法,代码更清晰。 - 善用枚举 (Enum):对于状态、分类等固定选项,使用 Enum 可以避免非法输入,并自动生成 Swagger UI 中的下拉选择框。
如果你有关于特定场景(如正则校验路径参数、动态路由等)的问题,可以随时告诉我!