Pydantic 2.0 完整指南
Pydantic 2.0 完整指南
什么是 Pydantic?
Pydantic 是一个 Python 数据验证和设置管理库,使用 Python 类型注解。它具有以下特点:
1. 核心功能
- 数据验证: 自动验证数据类型和约束条件
- 类型转换: 自动将输入数据转换为声明的类型
- Schema生成: 自动生成 JSON Schema
- IDE支持: 完整的类型提示支持
2. 主要优势
- 性能优秀(2.0版本比1.0快大约50倍)
- 使用直观,基于类型注解
- 与 FastAPI 完美集成
- 强大的错误处理机制
3. 常见使用场景
- API 请求/响应验证
- 配置管理
- 数据序列化/反序列化
- 数据库模型验证
一、基础用法
1. 基本模型定义
from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime
class User(BaseModel):
id: int
name: str = Field(..., min_length=2)
age: int = Field(gt=0, lt=150)
email: Optional[str] = None
created_at: datetime = Field(default_factory=datetime.now)
# 使用模型
user = User(id=1, name="John", age=30)
print(user.model_dump()) # 2.0中 dict() 改为 model_dump()
2. 类型注解
from typing import Union, List, Dict
from pydantic import constr
class Product(BaseModel):
name: constr(min_length=1, max_length=50) # 字符串约束
price: float = Field(gt=0)
tags: List[str] = []
metadata: Dict[str, Union[str, int]] = {}
二、新特性
1. 计算字段
from pydantic import computed_field
class Rectangle(BaseModel):
width: float
height: float
@computed_field
def area(self) -> float:
return self.width * self.height
2. 字段验证器
from pydantic import field_validator, model_validator
class Order(BaseModel):
items: List[str]
total: float
@field_validator('total')
def validate_total(cls, v):
if v < 0:
raise ValueError('Total must be positive')
return v
@model_validator(mode='after')
def validate_order(self) -> 'Order':
if not self.items and self.total > 0:
raise ValueError('Cannot have total without items')
return self
三、高级特性
1. 泛型模型
from typing import Generic, TypeVar
from pydantic import BaseModel
T = TypeVar('T')
class Response(BaseModel, Generic[T]):
code: int
data: T
message: str
class UserResponse(Response[User]):
pass
2. 自定义类型
from pydantic import GetCoreSchemaHandler
from pydantic_core import CoreSchema
from typing_extensions import Annotated
class Color:
def __init__(self, value: str):
self.value = value
@classmethod
def __get_pydantic_core_schema__(
cls,
_source_type: type[Any],
_handler: GetCoreSchemaHandler,
) -> CoreSchema:
return CoreSchema(
type='str',
pattern='^#[0-9a-fA-F]{6}$'
)
ColorType = Annotated[str, Color]
3. 嵌套模型
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
address: Address
alternate_addresses: List[Address] = []
四、数据验证
1. 基础验证
from pydantic import EmailStr, conint, confloat
class Employee(BaseModel):
email: EmailStr
age: conint(ge=18, le=65)
salary: confloat(gt=0)
department: str = Field(pattern='^[A-Z]{2,}$')
2. 自定义验证
from pydantic import ValidationError
class Transaction(BaseModel):
amount: float
currency: str
@field_validator('currency')
def validate_currency(cls, v):
if v not in ['USD', 'EUR', 'GBP']:
raise ValueError('Invalid currency')
return v.upper()
五、序列化
1. JSON处理
class Config(BaseModel):
name: str
data: Dict[str, Any]
class Config:
json_encoders = {
datetime: lambda v: v.isoformat()
}
# 序列化
config = Config(name="test", data={"time": datetime.now()})
json_str = config.model_dump_json()
# 反序列化
config = Config.model_validate_json(json_str)
2. 导出选项
class User(BaseModel):
id: int
password: str
email: str
class Config:
json_schema_extra = {
"example": {
"id": 1,
"password": "secret",
"email": "user@example.com"
}
}
# 排除字段
print(user.model_dump(exclude={'password'}))
六、实际应用示例
1. API请求验证
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
class UserCreate(BaseModel):
username: str = Field(min_length=3)
email: EmailStr
password: str = Field(min_length=8)
app = FastAPI()
@app.post("/users/")
async def create_user(user: UserCreate):
return user.model_dump(exclude={'password'})
2. 配置管理
from pydantic_settings import BaseSettings
from typing import Optional
class Settings(BaseSettings):
database_url: str
api_key: str
debug: bool = False
cache_ttl: Optional[int] = 300
class Config:
env_file = '.env'
env_file_encoding = 'utf-8'
settings = Settings()
3. 数据转换
from datetime import datetime
from pydantic import BaseModel, Field
class LogEntry(BaseModel):
timestamp: datetime
level: str = Field(pattern='^(INFO|WARNING|ERROR)$')
message: str
def to_dict(self):
return {
'time': self.timestamp.isoformat(),
'lvl': self.level[0],
'msg': self.message
}
七、性能优化
1. 使用Frozen Models
from pydantic import BaseModel
class Config(BaseModel):
model_config = ConfigDict(frozen=True)
name: str
value: int
2. 预编译验证
from pydantic import TypeAdapter
user_adapter = TypeAdapter(User)
# 批量验证
users = user_adapter.validate_python([
{"name": "John", "age": 30},
{"name": "Jane", "age": 25}
])
八、调试技巧
1. 错误处理
try:
user = User(name="", age=-1)
except ValidationError as e:
print(e.errors()) # 详细错误信息
print(e.json()) # JSON格式错误
2. Schema导出
print(User.model_json_schema()) # 查看JSON Schema