在 FastAPI 中,数据模型是处理请求和响应数据的核心,主要通过 Pydantic 库实现。
基本模型定义
Python
from pydantic import BaseModel
from typing import Optional, List
# Optional[str] 相当于 typing标准库下的Union[str, None]
# 定义数据模型
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None # 可选字段,默认值为 None
tags: List[str] = [] # 列表类型,默认空列表
# 用**解包字典并转换为模型
item_dict = {
"name": "苹果",
"price": 9.9,
"is_offer": True
}
item = Item(**item_dict)用于请求与响应
Python
@app.post("/items/")
async def create_item(item: Item):
# 可以直接访问模型的属性
item_dict = item.dict() # 转换为字典
if item.price:
item_dict.update({"price_with_tax": item.price * 1.1})
return item_dict
@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: int):
# 返回的数据会被验证并转换为 Item 模型格式
return {"name": "Example Item", "price": 99.9}数据验证与约束
Python
from pydantic import Field, EmailStr
# field约束
class UserCreate(BaseModel):
username: str = Field(..., min_length=3, max_length=50) # 必须字段,长度限制
email: EmailStr # 自动验证邮箱格式
age: Optional[int] = Field(None, ge=0, le=120) # 年龄范围 0-120
# 自定义约束
from pydantic import BaseModel, field_validator, ValidationError
from typing import Optional
class User(BaseModel):
username: str
password: str
age: Optional[int] = None
# 验证密码强度(至少8位,包含大小写字母和数字)
@field_validator('password')
def validate_password(cls, v):
if len(v) < 8:
raise ValueError('密码长度必须至少8位')
if not any(c.isupper() for c in v):
raise ValueError('密码必须包含大写字母')
if not any(c.islower() for c in v):
raise ValueError('密码必须包含小写字母')
if not any(c.isdigit() for c in v):
raise ValueError('密码必须包含数字')
return v
# 验证年龄(如果提供则必须为成年人)
@field_validator('age')
def validate_age(cls, v):
if v is not None and v < 18:
raise ValueError('年龄必须大于等于18岁')
return v
# 自定义多字段约束
from pydantic import BaseModel, model_validator
class Order(BaseModel):
total_amount: float
discount: float
final_amount: float
# 验证最终金额是否等于 总金额 - 折扣(误差允许±0.01)
@model_validator(mode='after') # mode='after' 表示在所有字段验证后执行
def validate_final_amount(cls, values):
total = values.total_amount
discount = values.discount
final = values.final_amount
if not abs(final - (total - discount)) < 0.01:
raise ValueError('最终金额计算错误')
return values模型配置
Python
class Item(BaseModel):
name: str
price: float
class Config:
orm_mode = True # 允许从 ORM 对象直接转换为模型
schema_extra = { # 文档示例
"example": {
"name": "Apple",
"price": 1.99
}
}模型继承
Python
class ItemBase(BaseModel):
name: str
price: float
class ItemCreate(ItemBase):
# 继承 ItemBase,添加创建时需要的字段
stock: int
class ItemResponse(ItemBase):
# 继承 ItemBase,添加响应中包含的字段
id: int
