Skip to content

Pydantic 与数据校验

模型定义、嵌套、Field 约束、校验器、序列化。

Updated View as Markdown
For humans

Pydantic 与数据校验

Pydantic 是 FastAPI 的数据层,也是 Python 数据建模的事实标准。面试主线:模型怎么定义、嵌套怎么处理、校验失败长什么样、怎么序列化。

模型定义与约束

from pydantic import BaseModel, Field, EmailStr

class UserCreate(BaseModel):
    name: str = Field(min_length=1, max_length=50)
    age: int = Field(ge=0, le=150)
    email: EmailStr
    tags: list[str] = Field(default_factory=list)
  • 类型注解即校验规则:类型错误、范围越界自动拦截
  • Field 约束:长度、范围、正则(pattern)、默认值
  • 内置类型:EmailStrHttpUrlUUIDdatetime(自动解析 ISO 格式)
  • 请求非法数据返回 422 校验错误(不是 400),响应体带字段级错误明细

嵌套模型

class Address(BaseModel):
    city: str
    zip_code: str

class Order(BaseModel):
    id: int
    user: UserCreate          # 嵌套模型
    items: list[Item]         # 模型列表
    metadata: dict[str, str]  # 泛型容器

嵌套自动递归校验:一层非法,整棵模型树报错。list[Model]dict[str, Model] 直接声明,无需手写解析。

校验器

from pydantic import field_validator, model_validator

class Booking(BaseModel):
    start: datetime
    end: datetime

    @field_validator("end")
    @classmethod
    def end_after_start(cls, v, info):
        if info.data.get("start") and v <= info.data["start"]:
            raise ValueError("结束时间必须晚于开始")
        return v
  • field_validator:单字段校验(可访问其他字段的值)
  • model_validator:整模型校验(跨字段逻辑)
  • 校验器在约束之后执行;抛 ValueError 转成 422
  • field_validator/model_validatorPydantic v2 的 API,v1 的 @validator 已弃用

序列化

user = UserCreate(name="alice", age=20)

data = user.model_dump()            # 转 dict
json_str = user.model_dump_json()   # 转 JSON 字符串
user2 = UserCreate.model_validate(data)   # 从 dict 构建+校验
方法 用途
model_dump() 转 dict(内部传递)
model_dump_json() 转 JSON(响应)
model_validate() 从 dict 构建并校验
model_copy(update=...) 部分修改(替代 Builder)

FastAPI 中:请求体自动 model_validate,响应模型自动 model_dump,手写序列化代码基本不需要。

面试追问

  1. Pydantic 和 dataclass 的区别? Pydantic 有校验、序列化、文档集成;dataclass 只是样板代码生成。FastAPI 用 Pydantic
  2. 校验失败返回什么? 422,响应体是字段级错误明细(loc/msg/type)。不是 400
  3. 嵌套模型怎么校验? 递归校验整棵模型树,一层错全报错。list[Model] 直接声明
  4. field_validator 和 model_validator? 前者单字段(可读其他字段),后者整模型跨字段逻辑。旧 @validator 已弃用
  5. 响应模型怎么过滤字段? 响应类型用 UserOut(不含 password 字段),FastAPI 自动按模型序列化
Navigation

Type to search…

↑↓ navigate↵ selectEsc close