Гайды
Pydantic: валидация и сериализация моделей
BaseModel и Field, validators, model_config, вложенные модели, pydantic-settings и типичные ошибки в API.
~11 мин чтения
Pydantic: валидация и сериализация моделей
Pydantic v2 (через pydantic-core на Rust) — основа тел запросов/ответов в FastAPI. Этот гайд про модели, валидацию, сериализацию и типичные паттерны. Связка с API — Быстрый старт с FastAPI.
1. BaseModel: поля и типы
from pydantic import BaseModel, Field, EmailStr
from datetime import datetime
class UserCreate(BaseModel):
email: EmailStr
name: str = Field(min_length=1, max_length=100)
age: int | None = Field(default=None, ge=0, le=150)
class UserRead(BaseModel):
model_config = {"from_attributes": True} # для ORM: read from object attrs
id: int
email: EmailStr
created_at: datetime
from_attributes (раньше orm_mode) позволяет строить ответ из SQLAlchemy/Django ORM объекта.
2. Валидаторы
field_validator — проверка/нормализация одного или нескольких полей:
from pydantic import field_validator
class PasswordReset(BaseModel):
password: str
password_repeat: str
@field_validator("password")
@classmethod
def strong(cls, v: str) -> str:
if len(v) < 12:
raise ValueError("min 12 chars")
return v
@field_validator("password_repeat")
@classmethod
def match(cls, v: str, info):
if "password" in info.data and v != info.data["password"]:
raise ValueError("passwords do not match")
return v
model_validator(mode="after") — целиком по собранной модели.
3. Настройки модели (model_config)
class Item(BaseModel):
model_config = {
"str_strip_whitespace": True,
"validate_assignment": True, # валидация при obj.field = x
"extra": "forbid", # запрет неизвестных полей в JSON
}
name: str
4. Вложенные модели и дискриминаторы
class Address(BaseModel):
city: str
street: str
class Order(BaseModel):
id: int
ship_to: Address
Для union-типов с полем «тип» используйте Discriminator (события разных видов в одном эндпоинте).
5. JSON и ORM
model_dump()— dict для JSON (режимmode="json"сериализуетdatetimeв ISO-строки).model_dump_json()— строка JSON.model_validate(data)— разбор dict/объекта в модель.
6. Настройки приложения: pydantic-settings
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
database_url: str
api_secret: str
settings = Settings()
Интеграция в FastAPI: зависимость get_settings() с lru_cache или Annotated[Settings, Depends()].
7. Алиасы полей (вход и выход)
Внешний JSON в camelCase, внутри модели — snake_case: используйте Field(alias="...") и populate_by_name=True, чтобы принимать оба варианта имени при необходимости. Для ответов в v2 — serialization_alias / AliasChoices (см. документацию Field).
from pydantic import BaseModel, ConfigDict, Field
class EventIn(BaseModel):
model_config = ConfigDict(populate_by_name=True)
event_type: str = Field(alias="eventType")
Так проще не дублировать DTO для мобильного клиента и бэкенда.
8. Частые ошибки
| Проблема | Решение |
|---|---|
ValidationError нечитаем в логах | Логировать e.errors() |
| Утечка внутренних полей в ответ | Отдельные модели Read без секретов |
| ORM lazy-load в async | Не отдавать ORM напрямую; явно собрать DTO |
9. Секреты и строгая конфигурация
Используйте SecretStr / SecretBytes для токенов и паролей — в model_dump() по умолчанию не попадут plain-text значения (для логов и ответов). Глобальные настройки моделей в v2 задаются через ConfigDict, а не вложенный класс Config.
from pydantic import BaseModel, ConfigDict, SecretStr
class WebhookIn(BaseModel):
model_config = ConfigDict(str_max_length=4096)
token: SecretStr
Связанные материалы
- Быстрый старт с FastAPI
- Маршрутизация и Dependency Injection
- asyncpg и асинхронные эндпоинты
- Async и БД в FastAPI (официальный раздел)
Дальше: тег Pydantic · тег Python