请求体与数据模型
为什么创建操作常用请求体
商品可能有名称、价格、库存、标签和描述。把这些全部塞进 URL 不方便;用 JSON 对象更容易描述它们的结构。
完整示例:
python
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class ProductCreate(BaseModel):
name: str = Field(min_length=1, max_length=100)
price: float = Field(gt=0)
stock: int = Field(ge=0)
description: str | None = None
tags: list[str] = Field(default_factory=list)
@app.post("/products", status_code=201)
def create_product(product: ProductCreate):
return product因为 product 是模型参数,FastAPI 默认从 JSON 请求体读取它。官方请求体说明
可提交:
json
{
"name": "入门教材",
"price": 39.9,
"stock": 10,
"tags": ["学习"]
}description 和 tags 可以省略;name、price、stock 必须提供。价格为负数或库存为负数会被拒绝。示例使用浮点数学习校验,真实金额通常要根据业务使用 Decimal 或整数最小货币单位。
请求体、路径、查询可以同时存在
追加到本章完整示例:
python
@app.put("/products/{product_id}")
def replace_product(
product_id: int,
product: ProductCreate,
notify: bool = False,
):
return {
"id": product_id,
"notify": notify,
"product": product,
}调用时:product_id 在路径中,notify 在查询字符串中,商品数据在请求体中。
一个 HTTP 请求只有一个请求体。多个模型参数不表示多个请求体,而是框架按参数名组织同一个 JSON 对象的结构。官方多个请求体参数说明
嵌套模型:对象里再放对象
下面是模型定义片段:
python
class Address(BaseModel):
city: str
street: str
class OrderCreate(BaseModel):
product_ids: list[int]
address: Address对应 JSON:
json
{
"product_ids": [1, 2],
"address": {
"city": "上海",
"street": "示例路 10 号"
}
}嵌套模型让每一层数据都有清楚的声明。比起只写一个没有字段规则的 dict,更容易定位错误。官方嵌套模型说明
Body(embed=True) 改变外层结构
追加到本章完整示例:
python
from typing import Annotated
from fastapi import Body
@app.post("/wrapped-products")
def create_wrapped_product(
product: Annotated[ProductCreate, Body(embed=True)],
):
return product这时客户端要提交:
json
{
"product": {
"name": "入门教材",
"price": 39.9,
"stock": 10
}
}单个模型默认可以直接接收商品对象;embed=True 要求加上 product 这一层。请求结构要与接口声明一致。
本章练习
定义订单模型,包含客户姓名、至少一个商品编号、收货地址。
提示:列表也可以用 Field(min_length=1) 约束元素数量。
过关标准:能把一份 JSON 写成模型,也能根据模型写出合法请求体。