「FastAPI进阶指南」请求与响应模型全解析
FastAPI作为基于Python的现代Web框架,凭借其高性能、自动文档生成和类型提示支持等特性,已成为构建RESTful API的首选工具。本文将围绕”请求与响应”这一核心主题,系统梳理FastAPI中路径参数、查询参数、请求体及响应模型的基础用法,结合实际开发场景提供可落地的解决方案。
一、路径参数:精准定位资源
路径参数是URL中用于标识特定资源的变量部分,在FastAPI中通过{参数名}语法定义。例如在用户管理系统中,/users/{user_id}路径中的user_id即为路径参数。
1.1 基础声明方式
from fastapi import FastAPIapp = FastAPI()@app.get("/users/{user_id}")async def read_user(user_id: int):return {"user_id": user_id}
上述代码展示了路径参数的基本声明:
- 使用
{user_id}在路径中定义参数位置 - 通过类型注解
int约束参数类型 - FastAPI会自动将字符串路径参数转换为指定类型
1.2 路径参数转换规则
FastAPI内置了完善的类型转换机制:
| 类型注解 | 转换行为 | 示例 |
|————-|————-|———|
| int | 字符串转整数 | “/users/123” → 123 |
| float | 字符串转浮点数 | “/items/3.14” → 3.14 |
| bool | 字符串转布尔值 | “/enable/true” → True |
| str | 保持原样 | “/names/John” → “John” |
当类型不匹配时,FastAPI会自动返回422错误响应,例如访问/users/abc会触发验证失败。
1.3 路径参数命名约束
路径参数命名需遵循Python变量命名规范:
- 只能包含字母、数字和下划线
- 不能以数字开头
- 推荐使用小写字母和下划线组合(如
user_id)
二、查询参数:灵活筛选数据
查询参数是URL中?后面的键值对,用于对资源进行筛选或排序。例如/users/?limit=10&skip=20包含两个查询参数。
2.1 基本查询参数
@app.get("/items/")async def read_items(skip: int = 0, limit: int = 10):return {"skip": skip, "limit": limit}
关键特性:
- 通过类型注解声明参数类型
- 使用
=设置默认值(可选参数) - 参数顺序不影响调用(
/items/?limit=5&skip=10等效)
2.2 可选查询参数
from typing import Optional@app.get("/users/{user_id}/items/")async def read_user_items(user_id: int,q: Optional[str] = None,short: bool = False):items = f"DB查询用户{user_id}的物品"if q:items += f" 筛选条件: {q}"if short:return {"items": items[:50]}return {"items": items}
实际应用场景:
- 搜索功能(
q参数) - 响应格式控制(
short参数) - 分页参数(
page、per_page)
2.3 查询参数验证
FastAPI支持Pydantic模型进行复杂验证:
from pydantic import BaseModel, constrclass QueryParams(BaseModel):q: Optional[constr(max_length=50)] = Nonelimit: int = 100sort: Optional[str] = None@app.get("/search/")async def search(params: QueryParams):return {"params": params}
优势:
- 集中管理查询参数
- 内置字段验证(如字符串长度限制)
- 自动生成API文档
三、请求体:结构化数据传输
当需要传输复杂数据时,请求体(Request Body)是更合适的选择。FastAPI通过Pydantic模型实现高效的请求体处理。
3.1 基础请求体
from pydantic import BaseModelclass Item(BaseModel):name: strdescription: Optional[str] = Noneprice: floattax: Optional[float] = None@app.post("/items/")async def create_item(item: Item):item_dict = item.dict()if item.tax:price_with_tax = item.price + item.taxitem_dict.update({"price_with_tax": price_with_tax})return item_dict
工作原理:
- 客户端发送JSON请求体
- FastAPI自动反序列化为Item对象
- 通过
item.dict()转换为字典 - 支持嵌套模型和复杂验证
3.2 多请求体支持
FastAPI支持同时接收多个请求体参数:
@app.put("/items/{item_id}")async def update_item(item_id: int,item: Item,user: User, # 假设存在User模型importance: int = Body(...)):results = {"item_id": item_id,"item": item,"user": user,"importance": importance}return results
Body(...)语法表示该参数为必填项。
3.3 请求体验证
Pydantic模型提供强大的验证功能:
from pydantic import EmailStr, HttpUrl, conintclass UserIn(BaseModel):username: stremail: EmailStrfull_name: Optional[str] = Nonewebsite: Optional[HttpUrl] = Noneage: conint(ge=0, le=120) = 18 # 0 ≤ age ≤ 120
验证规则示例:
EmailStr:自动验证邮箱格式HttpUrl:验证URL有效性conint:约束数值范围
四、响应模型:精准控制输出
响应模型决定了API返回的数据结构,FastAPI通过类型注解自动处理序列化。
4.1 基础响应模型
@app.post("/items/", response_model=Item)async def create_item(item: Item):return item # 自动序列化为JSON
关键特性:
- 使用
response_model指定返回类型 - 自动过滤未声明的字段
- 支持嵌套模型
4.2 响应模型字段控制
class ItemOut(BaseModel):name: strprice: float# 不包含description和tax字段@app.post("/items/simple/", response_model=ItemOut)async def create_simple_item(item: Item):return item # 只返回ItemOut中声明的字段
应用场景:
- 返回计算字段(如总价)
- 隐藏敏感信息
- 简化复杂对象
4.3 响应状态码与头部
from fastapi import Response, status@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)async def create_item(item: Item, response: Response):response.headers["X-Custom-Header"] = "Hello"return item
扩展功能:
- 自定义HTTP状态码
- 添加响应头部
- 结合Pydantic模型使用
五、最佳实践总结
- 参数类型明确:始终为路径参数和查询参数添加类型注解
- 模型复用:创建共享的Pydantic模型减少代码重复
- 分页实现:推荐使用
limit/offset或page/per_page模式 - 版本控制:通过路径前缀(如
/v1/)管理API版本 - 文档增强:利用OpenAPI注解补充API说明
六、性能优化建议
- 异步处理:对I/O密集型操作使用
async def - 数据验证前置:尽早验证请求数据减少无效处理
- 响应缓存:对静态响应考虑使用缓存中间件
- 模型扁平化:避免过深的嵌套模型影响序列化性能
通过系统掌握这些核心机制,开发者能够高效构建出稳定、可维护的FastAPI应用。实际开发中,建议结合Postman等工具进行API测试,同时利用FastAPI自动生成的交互式文档(访问/docs路径)提升开发效率。