FastAPI 的核心功能之一:请求体(Request Body)。
请求体主要用于 POST、PUT、PATCH 等 HTTP 方法中,用来接收客户端发送的 JSON 数据(比如创建用户、提交表单、上传配置等)。
🧩 一、什么是请求体(Request Body)?
- 请求体是 HTTP 请求中
Content-Type: application/json的数据部分。 例如,前端发送:
POST /users/ { "name": "Alice", "age": 30, "email": "alice@example.com" }这个 JSON 就是 请求体。
✅ 在 FastAPI 中,请求体通过 Pydantic 模型(BaseModel) 定义和校验。
✅ 二、基本用法:定义模型 + 接收请求体
🔹 步骤 1:导入并定义 Pydantic 模型
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class UserCreate(BaseModel):
name: str
age: int
email: str💡 BaseModel 是 Pydantic 提供的基类,用于定义数据结构。🔹 步骤 2:在路由函数中使用模型作为参数
@app.post("/users/")
def create_user(user: UserCreate):
return {
"message": f"User {user.name} created!",
"user": user
}FastAPI 会自动:
- 解析 JSON 请求体
- 校验字段类型(
name必须是字符串,age必须是整数) - 转换为
UserCreate对象 - 如果校验失败 → 自动返回 422 错误
🔹 测试示例
请求:
POST /users/
Content-Type: application/json
{
"name": "Bob",
"age": 25,
"email": "bob@example.com"
}响应:
{
"message": "User Bob created!",
"user": {
"name": "Bob",
"age": 25,
"email": "bob@example.com"
}
}错误请求(缺少字段):
{ "name": "Bob" } // 缺少 age 和 email→ 自动返回 422,详细说明缺失字段!
⚠️ 三、重要注意事项(新手必看)
1️⃣ 请求体只能有一个(主参数)
FastAPI 规定:一个路由中只能有一个请求体参数(即一个 Pydantic 模型)。
# ❌ 错误:两个请求体?
@app.post("/items/")
def create_item(item: Item, user: User): # 不行!✅ 正确做法:把多个数据合并到一个模型中,或使用 混合参数(见下文)。
2️⃣ 请求体参数不能有默认值(除非嵌套)
# ❌ 这样写会被 FastAPI 当作查询参数!
def create_user(user: UserCreate = None):✅ 请求体参数不要设默认值,它本身就是可选/必需由模型字段决定。
3️⃣ 字段默认值 & 可选字段
在模型中控制字段是否必需:
from typing import Optional
class UserCreate(BaseModel):
name: str # 必需
age: int = 18 # 可选,默认 18
email: Optional[str] = None # 可选,可为 None- 请求
{ "name": "Alice" }→ 合法 user.age会自动设为18
💡 Python 3.10+ 可用str | None代替Optional[str]
🛠 四、高级用法
🔸 1. 嵌套模型(Nested Models)
class Address(BaseModel):
city: str
country: str
class UserCreate(BaseModel):
name: str
address: Address # 嵌套
@app.post("/users/")
def create_user(user: UserCreate):
return user请求体:
{
"name": "Alice",
"address": {
"city": "Beijing",
"country": "China"
}
}🔸 2. 混合使用:路径参数 + 查询参数 + 请求体
这是最常见场景!
@app.put("/users/{user_id}")
def update_user(
user_id: int, # ← 路径参数
active: bool = True, # ← 查询参数(?active=false)
user: UserCreate # ← 请求体(JSON)
):
return {
"user_id": user_id,
"active": active,
"updated_data": user
}请求:
PUT /users/123?active=false
Content-Type: application/json
{
"name": "Alice Updated",
"age": 31,
"email": "alice.new@example.com"
}✅ FastAPI 能完美区分三者!
🔸 3. 使用 Field 添加校验和文档
类似 Query,可用 Field 控制模型字段:
from pydantic import BaseModel, Field
class UserCreate(BaseModel):
name: str = Field(..., min_length=2, max_length=50)
age: int = Field(ge=0, le=120) # 0 ≤ age ≤ 120
email: str
# ... 路由不变...表示该字段必需- 自动校验 + 生成 OpenAPI 文档说明
📊 五、请求体 vs 查询参数 vs 路径参数 —— 一句话总结
| 类型 | 用途 | HTTP 方法 | 是否必需 | 示例 |
|---|---|---|---|---|
| 路径参数 | 标识资源 | GET/PUT/DELETE | ✅ 是 | /users/123 |
| 查询参数 | 过滤/分页/选项 | 通常 GET | ❌ 否 | ?page=2&limit=10 |
| 请求体 | 提交复杂数据 | POST/PUT/PATCH | ✅ 由模型决定 | JSON 数据 |
✅ 六、最佳实践建议
- 始终用 Pydantic 模型定义请求体 → 自动校验 + 文档 + 类型安全
- 不要混用多个请求体 → 合并到一个模型中
敏感字段(如密码)记得加校验:
password: str = Field(..., min_length=8)- 使用嵌套模型表达复杂结构(如订单含商品列表)
- 利用 FastAPI 自动生成的交互式文档(访问
/docs测试!)
🎯 小练习
写一个 API 用于创建商品:
- 路径:
POST /products/ 请求体包含:
name: strprice: float(必须 > 0)tags: list[str](可选,默认空列表)
- 返回创建的商品信息
from fastapi import FastAPI
from pydantic import BaseModel, Field
from typing import List
app = FastAPI()
class ProductCreate(BaseModel):
name: str
price: float = Field(gt=0) # greater than 0
tags: List[str] = []
@app.post("/products/")
def create_product(product: ProductCreate):
return {
"id": 1001, # 模拟 ID
"product": product
}