Pydantic 基础 #

什么是 Pydantic? #

Pydantic 是一个使用 Python 类型注解进行数据验证和设置管理的库。它是 FastAPI 的核心依赖之一。

text
┌─────────────────────────────────────────────────────────────┐
│                    Pydantic 的作用                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   输入数据 ────> Pydantic 模型 ────> 验证后的数据            │
│                                                             │
│   功能:                                                    │
│   ✅ 数据验证                                               │
│   ✅ 类型转换                                               │
│   ✅ 序列化/反序列化                                        │
│   ✅ JSON Schema 生成                                       │
│   ✅ 设置管理                                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

安装 #

bash
pip install pydantic

基本模型 #

定义模型 #

python
from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str
    email: str
    age: int | None = None

创建实例 #

python
user = User(id=1, name='John', email='john@example.com')
print(user)
# id=1 name='John' email='john@example.com' age=None

user = User(id=1, name='John', email='john@example.com', age=30)
print(user)
# id=1 name='John' email='john@example.com' age=30

从字典创建 #

python
user_data = {
    'id': 1,
    'name': 'John',
    'email': 'john@example.com'
}
user = User(**user_data)

类型转换 #

python
user = User(id='1', name='John', email='john@example.com')
print(user.id)  # 1 (自动转换为 int)
print(type(user.id))  # <class 'int'>

字段类型 #

基本类型 #

python
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float
    quantity: int
    is_active: bool

可选类型 #

python
from typing import Optional

class User(BaseModel):
    name: str
    age: Optional[int] = None
    # 或 Python 3.10+ 语法
    age: int | None = None

集合类型 #

python
from typing import List, Dict, Set, Tuple

class Data(BaseModel):
    items: list[str]           # 字符串列表
    mapping: dict[str, int]    # 字典
    unique: set[int]           # 集合
    coordinates: tuple[int, int]  # 元组

复杂类型 #

python
from typing import List, Dict, Any

class Complex(BaseModel):
    list_of_dicts: List[Dict[str, Any]]
    nested: Dict[str, List[int]]
    any_value: Any

特殊类型 #

日期时间 #

python
from datetime import datetime, date, time, timedelta
from pydantic import BaseModel

class Event(BaseModel):
    created_at: datetime
    event_date: date
    start_time: time
    duration: timedelta

event = Event(
    created_at='2024-01-15T10:30:00',
    event_date='2024-01-20',
    start_time='14:00:00',
    duration='1:30:00'
)

URL 和 Email #

python
from pydantic import BaseModel, HttpUrl, EmailStr

class Contact(BaseModel):
    email: EmailStr
    website: HttpUrl

contact = Contact(
    email='user@example.com',
    website='https://example.com'
)

UUID #

python
from uuid import UUID
from pydantic import BaseModel

class Resource(BaseModel):
    id: UUID

resource = Resource(id='123e4567-e89b-12d3-a456-426614174000')

枚举 #

python
from enum import Enum
from pydantic import BaseModel

class Status(str, Enum):
    pending = 'pending'
    approved = 'approved'
    rejected = 'rejected'

class Item(BaseModel):
    status: Status

item = Item(status='pending')
print(item.status)  # Status.pending

Field 函数 #

基本用法 #

python
from pydantic import BaseModel, Field

class Item(BaseModel):
    name: str = Field(..., description='Item name')
    price: float = Field(..., gt=0, description='Item price')
    quantity: int = Field(default=0, ge=0)

字段约束 #

python
class Product(BaseModel):
    name: str = Field(
        ...,
        min_length=2,
        max_length=50,
        description='Product name'
    )
    price: float = Field(
        ...,
        gt=0,
        le=10000,
        description='Price in dollars'
    )
    discount: float = Field(
        default=0,
        ge=0,
        le=1,
        description='Discount rate (0-1)'
    )
    quantity: int = Field(
        default=0,
        ge=0,
        description='Stock quantity'
    )

默认值 #

python
from datetime import datetime

class Order(BaseModel):
    created_at: datetime = Field(default_factory=datetime.now)
    items: list[str] = Field(default_factory=list)

别名 #

python
class User(BaseModel):
    username: str = Field(..., alias='user_name')
    email: str = Field(..., alias='email_address')

user = User(user_name='john', email_address='john@example.com')
print(user.username)  # john

示例 #

python
class Item(BaseModel):
    name: str = Field(..., examples=['iPhone 15'])
    price: float = Field(..., examples=[999.99])

验证器 #

field_validator #

python
from pydantic import BaseModel, field_validator

class User(BaseModel):
    name: str
    username: str
    
    @field_validator('username')
    @classmethod
    def username_alphanumeric(cls, v: str) -> str:
        if not v.isalnum():
            raise ValueError('must be alphanumeric')
        return v.lower()

多字段验证器 #

python
class User(BaseModel):
    username: str
    email: str
    
    @field_validator('username', 'email')
    @classmethod
    def lowercase(cls, v: str) -> str:
        return v.lower()

model_validator #

python
from pydantic import BaseModel, model_validator

class User(BaseModel):
    password: str
    confirm_password: str
    
    @model_validator(mode='after')
    def passwords_match(self):
        if self.password != self.confirm_password:
            raise ValueError('passwords do not match')
        return self

验证前后处理 #

python
class Item(BaseModel):
    name: str
    price: float
    
    @field_validator('name')
    @classmethod
    def strip_name(cls, v: str) -> str:
        return v.strip()
    
    @field_validator('price')
    @classmethod
    def round_price(cls, v: float) -> float:
        return round(v, 2)

模型方法 #

model_dump #

python
user = User(id=1, name='John', email='john@example.com')

user_dict = user.model_dump()
# {'id': 1, 'name': 'John', 'email': 'john@example.com'}

user_dict = user.model_dump(exclude={'email'})
# {'id': 1, 'name': 'John'}

user_dict = user.model_dump(include={'id', 'name'})
# {'id': 1, 'name': 'John'}

model_dump_json #

python
user_json = user.model_dump_json()
# '{"id":1,"name":"John","email":"john@example.com"}'

model_validate #

python
user = User.model_validate({'id': 1, 'name': 'John', 'email': 'john@example.com'})

model_validate_json #

python
user = User.model_validate_json('{"id":1,"name":"John","email":"john@example.com"}')

模型配置 #

ConfigDict #

python
from pydantic import BaseModel, ConfigDict

class Item(BaseModel):
    model_config = ConfigDict(
        str_strip_whitespace=True,
        validate_assignment=True,
        extra='forbid'
    )
    
    name: str
    price: float

常用配置 #

text
┌─────────────────────────────────────────────────────────────┐
│                    模型配置选项                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   str_strip_whitespace    自动去除字符串空白                 │
│   str_to_lower            自动转小写                        │
│   str_to_upper            自动转大写                        │
│   validate_assignment     赋值时验证                         │
│   extra                   额外字段处理                       │
│                          'ignore' 忽略                       │
│                          'forbid' 禁止(报错)               │
│                          'allow' 允许                        │
│   populate_by_name        允许通过字段名填充                  │
│   from_attributes         从对象属性读取                     │
│   use_enum_values         使用枚举值而非枚举对象              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

配置示例 #

python
class User(BaseModel):
    model_config = ConfigDict(
        str_strip_whitespace=True,
        validate_assignment=True,
        extra='forbid'
    )
    
    name: str
    email: str

user = User(name='  John  ', email='john@example.com')
print(user.name)  # 'John' (已去除空白)

user.name = '  Jane  '
print(user.name)  # 'Jane' (赋值时也验证)

嵌套模型 #

简单嵌套 #

python
class Address(BaseModel):
    street: str
    city: str
    country: str

class User(BaseModel):
    name: str
    address: Address

user = User(
    name='John',
    address={
        'street': '123 Main St',
        'city': 'New York',
        'country': 'USA'
    }
)

列表嵌套 #

python
class Item(BaseModel):
    name: str
    price: float

class Order(BaseModel):
    items: list[Item]
    total: float

order = Order(
    items=[
        {'name': 'Item 1', 'price': 10.0},
        {'name': 'Item 2', 'price': 20.0}
    ],
    total=30.0
)

继承 #

模型继承 #

python
class UserBase(BaseModel):
    email: str
    full_name: str | None = None

class UserCreate(UserBase):
    password: str

class User(UserBase):
    id: int
    is_active: bool = True

class UserInDB(User):
    hashed_password: str

完整示例 #

python
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field, EmailStr, field_validator, ConfigDict

class Address(BaseModel):
    street: str = Field(..., min_length=5)
    city: str = Field(..., min_length=2)
    country: str = Field(..., min_length=2)
    postal_code: str = Field(..., pattern=r'^\d{5}$')

class UserBase(BaseModel):
    model_config = ConfigDict(
        str_strip_whitespace=True,
        validate_assignment=True
    )
    
    username: str = Field(
        ...,
        min_length=3,
        max_length=20,
        pattern='^[a-zA-Z0-9_]+$'
    )
    email: EmailStr
    full_name: Optional[str] = Field(None, min_length=2)
    
    @field_validator('username')
    @classmethod
    def username_lowercase(cls, v: str) -> str:
        return v.lower()

class UserCreate(UserBase):
    password: str = Field(..., min_length=8)
    confirm_password: str
    
    @field_validator('confirm_password')
    @classmethod
    def passwords_match(cls, v: str, info) -> str:
        if 'password' in info.data and v != info.data['password']:
            raise ValueError('passwords do not match')
        return v

class User(UserBase):
    id: int
    address: Optional[Address] = None
    created_at: datetime = Field(default_factory=datetime.now)
    is_active: bool = True

class UserInDB(User):
    hashed_password: str

下一步 #

现在你已经掌握了 Pydantic 基础,接下来学习 依赖注入,了解 FastAPI 强大的依赖系统!

最后更新:2026-03-29