Pydantic数据验证框架Skill pydantic

Pydantic是一个强大的Python数据验证和设置管理框架,使用类型注解定义数据模式,提供自动类型转换、序列化/反序列化功能。适用于API开发、配置管理、数据清洗等场景,确保应用程序的类型安全和数据完整性。关键词:Python数据验证、类型注解、序列化、数据模型、API开发、配置管理、类型安全、Pydantic框架

后端开发 0 次安装 0 次浏览 更新于 3/2/2026

名称: pydantic 描述: 使用Python类型注解进行数据验证和设置管理,基于Pydantic v2 使用场景: 当您需要验证数据结构、创建设置模型、序列化/反序列化数据,或在Python应用程序中确保类型安全时

Pydantic v2 框架技能

Pydantic是一个数据验证库,它使用Python类型注解来定义数据模式,提供快速且可扩展的验证,并支持自动类型转换。

快速开始

基础模型定义

from pydantic import BaseModel
from datetime import datetime
from typing import Optional

class User(BaseModel):
    id: int
    name: str
    email: str
    signup_ts: Optional[datetime] = None
    is_active: bool = True

# 自动类型转换
user = User(
    id='123',  # 字符串 → 整数
    name='John Doe',
    email='john@example.com',
    signup_ts='2017-06-01 12:22'  # 字符串 → 日期时间
)

从数据源验证

# 从字典
user = User.model_validate({'id': 1, 'name': 'Alice', 'email': 'alice@test.com'})

# 从JSON
user = User.model_validate_json('{"id": 1, "name": "Alice", "email": "alice@test.com"}')

# 序列化
print(user.model_dump())  # Python字典
print(user.model_dump_json())  # JSON字符串

常用模式

字段配置

from pydantic import BaseModel, Field, EmailStr, HttpUrl
from typing import Annotated

class Product(BaseModel):
    product_id: int = Field(alias='id', ge=1, description='唯一产品标识符')
    name: str = Field(min_length=1, max_length=200)
    price: float = Field(gt=0, le=1000000)
    email: EmailStr
    website: HttpUrl
    tags: list[str] = Field(default_factory=list, max_length=10)
    internal_code: str = Field(exclude=True, default='N/A')

class User(BaseModel):
    username: Annotated[str, Field(min_length=3, pattern=r'^[a-zA-Z0-9_]+$')]
    age: int = Field(ge=0, le=150)

模型配置

from pydantic import BaseModel, ConfigDict

class StrictModel(BaseModel):
    model_config = ConfigDict(
        strict=True,              # 无类型转换
        frozen=True,              # 不可变实例
        validate_assignment=True, # 属性赋值时验证
        extra='forbid',           # 拒绝额外字段
        str_strip_whitespace=True,
        populate_by_name=True,    # 接受别名和字段名
        use_enum_values=True,     # 序列化枚举为值
    )

    id: int
    name: str

自定义验证

from pydantic import BaseModel, model_validator, field_validator, ValidationError
from typing import Any

class DateRange(BaseModel):
    start_date: str
    end_date: str

    @field_validator('start_date', 'end_date')
    @classmethod
    def validate_date_format(cls, v: str) -> str:
        # 自定义验证逻辑
        if not v:
            raise ValueError('日期不能为空')
        return v

    @model_validator(mode='after')
    def check_dates_order(self) -> 'DateRange':
        # 跨字段验证
        if self.start_date > self.end_date:
            raise ValueError('开始日期必须在结束日期之前')
        return self

# 使用模型
try:
    date_range = DateRange(start_date='2024-01-01', end_date='2024-01-31')
except ValidationError as e:
    for error in e.errors():
        print(f"{error['loc']}: {error['msg']}")

序列化控制

from pydantic import BaseModel, Field, SecretStr
from datetime import datetime

class User(BaseModel):
    id: int
    username: str
    password: SecretStr
    created_at: datetime
    internal_data: dict = Field(exclude=True, default_factory=dict)

# 序列化选项
user = User(
    id=1,
    username='john',
    password='secret',
    created_at=datetime.now()
)

# 基础序列化
print(user.model_dump())  # Python字典
print(user.model_dump_json())  # JSON字符串

# 排除字段
print(user.model_dump(exclude={'password'}))
print(user.model_dump(exclude={'username', 'created_at'}))

# 仅包含特定字段
print(user.model_dump(include={'id', 'username'}))

# JSON兼容序列化
print(user.model_dump(mode='json'))  # 日期时间 → 字符串
print(user.model_dump(by_alias=True))  # 使用字段别名

自定义序列化

from typing import Annotated, Any
from pydantic import BaseModel, field_serializer, PlainSerializer

class Model(BaseModel):
    number: int
    created_at: datetime

    @field_serializer('number')
    def serialize_number(self, value: int) -> str:
        return f"{value:,}"  # 用逗号格式化

    # 使用Annotated和PlainSerializer
    custom_field: Annotated[
        float,
        PlainSerializer(lambda x: round(x, 2), return_type=float)
    ]

嵌套模型和关系

from pydantic import BaseModel
from typing import Optional, List

class Address(BaseModel):
    street: str
    city: str
    country: str = 'USA'
    zip_code: str

class User(BaseModel):
    id: int
    name: str
    addresses: List[Address]
    primary_address: Optional[Address] = None

# 使用
user = User(
    id=1,
    name='John Doe',
    addresses=[
        {'street': '123 Main St', 'city': 'New York', 'zip_code': '10001'},
        {'street': '456 Oak Ave', 'city': 'Boston', 'zip_code': '02101'}
    ],
    primary_address={'street': '123 Main St', 'city': 'New York', 'zip_code': '10001'}
)

枚举集成

from enum import Enum, IntEnum
from pydantic import BaseModel

class Status(str, Enum):
    PENDING = 'pending'
    ACTIVE = 'active'
    COMPLETED = 'completed'

class Priority(IntEnum):
    LOW = 1
    MEDIUM = 2
    HIGH = 3

class Task(BaseModel):
    title: str
    status: Status = Status.PENDING
    priority: Priority = Priority.MEDIUM

    model_config = ConfigDict(use_enum_values=True)

# 可以使用枚举值或名称
task1 = Task(title='任务1', status='active', priority=3)
task2 = Task(title='任务2', status=Status.ACTIVE, priority=Priority.HIGH)

TypeAdapter用于独立验证

from pydantic import TypeAdapter
from typing import List, Optional

# 无需完整模型验证单个类型
int_adapter = TypeAdapter(int)
print(int_adapter.validate_python('123'))  # 123

list_adapter = TypeAdapter(List[int])
print(list_adapter.validate_python(['1', '2', '3']))  # [1, 2, 3]

# 生成JSON模式
print(int_adapter.json_schema())
print(list_adapter.json_schema())

数据验证模式

from pydantic import BaseModel, ValidationError
from typing import Union

class EmailValidator(BaseModel):
    email: str

    @field_validator('email')
    @classmethod
    def validate_email(cls, v: str) -> str:
        if '@' not in v:
            raise ValueError('无效的邮箱格式')
        return v.lower()

# 验证错误处理
try:
    user = User(id='invalid', name='', email='test')
except ValidationError as e:
    print(f"错误: {e.error_count()}")
    for error in e.errors():
        print(f"  {error['loc']}: {error['msg']} ({error['type']})")

要求

  • Python 3.8+
  • Pydantic v2.x: uv add pydantic
  • 增强类型的可选依赖:
    • uv add pydantic[email] 用于EmailStr
    • uv add pydantic[url] 用于HttpUrl
    • uv add pydantic[typing-extensions] 用于扩展类型支持

最佳实践

  1. 使用特定类型: 对于正数,优先使用conint(gt=0)而非int
  2. 配置模型: 使用ConfigDict设置全局模型行为
  3. 处理验证错误: 始终在try/catch块中包装模型创建
  4. 使用字段验证器: 使用@field_validator实现自定义验证逻辑
  5. 控制序列化: 使用model_dump()参数控制输出格式
  6. 利用类型转换: Pydantic自动转换兼容类型
  7. 使用嵌套模型: 将复杂数据分解为更小、可重用的模型