Pydantic v2:Python 数据验证的终极武器


Pydantic v2 是什么

Pydantic 是 Python 最流行的数据验证库,FastAPI 的核心依赖。v2 版本用 Rust 重写了核心,速度比 v1 快 5-50 倍

pip install pydantic  # 现在默认装 v2

基础用法

from pydantic import BaseModel, EmailStr, Field
from datetime import datetime
from typing import Optional

class User(BaseModel):
    id: int
    name: str = Field(min_length=2, max_length=50)
    email: EmailStr
    age: Optional[int] = Field(default=None, ge=0, le=150)
    created_at: datetime = Field(default_factory=datetime.now)

# 创建实例 — 自动验证
user = User(id=1, name="BOSS", email="boss@example.com", age=25)
print(user.model_dump())
# {'id': 1, 'name': 'BOSS', 'email': 'boss@example.com', 'age': 25, ...}

# 数据有问题时会抛出 ValidationError
try:
    bad_user = User(id="not-a-number", name="X", email="invalid")
except Exception as e:
    print(e)  # 详细的错误信息

v2 新特性速览

1. model_validator — 模型级验证

from pydantic import BaseModel, model_validator

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

    @model_validator(mode='after')
    def check_dates(self) -> 'DateRange':
        if self.end <= self.start:
            raise ValueError('end 必须晚于 start')
        return self

# ✅ 正常
DateRange(start=datetime(2026,1,1), end=datetime(2026,12,31))

# ❌ 抛出 ValidationError
DateRange(start=datetime(2026,12,31), end=datetime(2026,1,1))

2. field_validator — 字段级验证

from pydantic import BaseModel, field_validator

class Product(BaseModel):
    name: str
    price: float
    sku: str

    @field_validator('price')
    @classmethod
    def price_must_be_positive(cls, v: float) -> float:
        if v <= 0:
            raise ValueError('价格必须大于 0')
        return round(v, 2)  # 自动四舍五入到分

    @field_validator('sku')
    @classmethod
    def sku_format(cls, v: str) -> str:
        v = v.upper().strip()
        if not v.startswith('SKU-'):
            raise ValueError('SKU 必须以 SKU- 开头')
        return v

3. 序列化控制

from pydantic import BaseModel, field_serializer
from datetime import datetime

class Post(BaseModel):
    title: str
    published_at: datetime
    view_count: int = 0

    @field_serializer('published_at')
    def serialize_date(self, dt: datetime) -> str:
        return dt.strftime('%Y-%m-%d %H:%M')

post = Post(title="Hello", published_at=datetime.now())
print(post.model_dump())
# {'title': 'Hello', 'published_at': '2026-03-11 22:00', 'view_count': 0}

# JSON 序列化
print(post.model_dump_json())

与 FastAPI 配合

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class CreateUserRequest(BaseModel):
    name: str
    email: EmailStr

class UserResponse(BaseModel):
    id: int
    name: str
    email: str

@app.post("/users", response_model=UserResponse)
async def create_user(body: CreateUserRequest):
    # body 已经过验证,直接用
    return UserResponse(id=1, name=body.name, email=body.email)

FastAPI 会自动用 Pydantic 验证请求体,并根据 response_model 过滤返回字段。


知识卡片 📌

Pydantic v2 核心:

数据输入         验证          输出
dict/JSON  →  BaseModel  →  model_dump()
str        →  类型转换    →  model_dump_json()

         ValidationError(失败时)

常用 Field 参数:
  gt / ge / lt / le  →  数值范围
  min_length / max_length  →  字符串长度
  pattern  →  正则表达式
  default / default_factory  →  默认值

Pydantic v2 是现代 Python 项目的标配,FastAPI + Pydantic = 后端开发最强组合。