Pydantic: валидация данных в Python — BaseModel, Field и кастомные валидаторы
Pydantic превращает аннотации типов в правила валидации: неправильные данные отсеиваются с понятным списком ошибок ещё до вашего кода. Разбираем от BaseModel до собственных валидаторов — с примерами и типичными граблями.
Обновлено 18 сентября 2026
BaseModel: описание данных в три строки
Модель pydantic — обычный класс, наследующий BaseModel. Аннотации типов становятся правилами: при создании объекта pydantic проверит значения и приведёт совместимые типы.
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
email: str
user = User(id=1, name="Анна", email="anna@example.com")
print(user.name) # Анна
User(id="2", name="Иван", email="ivan@example.com")
# строка "2" тихо превратилась в число 2 — pydantic приводит совместимые типы
Что будет с неправильными данными: ValidationError
User(id="abc", name="", email="не-почта")
# pydantic_core.ValidationError: 3 validation errors for User
# id: Input should be a valid integer [type=int_parsing]
# name: String should have at least 1 character [type=string_too_short]
# email: value is not a valid email address [type=value_error]
Ограничения полей: Field
Типа «строка» мало — нужен email корректного вида, возраст от 18, пароль не короче восьми символов. Ограничения задаются через Field.
from pydantic import BaseModel, Field, EmailStr
class User(BaseModel):
id: int = Field(ge=1) # >= 1
name: str = Field(min_length=2, max_length=50)
email: EmailStr # проверка email
age: int = Field(ge=18, le=120)
phone: str = Field(pattern=r"^\+7\d{10}$") # +7 и 10 цифр
Кастомные валидаторы: @field_validator
Когда правил Field недостаточно (приведение к формату, бизнес-проверка), пишется свой валидатор.
from pydantic import BaseModel, field_validator
class Order(BaseModel):
items_count: int
@field_validator("items_count")
@classmethod
def not_zero(cls, v: int) -> int:
if v <= 0:
raise ValueError("заказ должен содержать хотя бы один товар")
return v # обязательно верните значение
Order(items_count=0)
# ValidationError: заказ должен содержать хотя бы один товар
Если правило смотрит сразу на несколько полей (дата выезда позже даты заезда), берите @model_validator(mode="after") — он получает уже собранную модель.
Вложенные модели и списки
class Address(BaseModel):
city: str
street: str
class Client(BaseModel):
name: str
address: Address # вложенная модель
tags: list[str] = []
client = Client(
name="Анна",
address={"city": "Москва", "street": "Тверская, 1"},
)
print(client.address.city) # Москва
Грабли перехода с v1 на v2
@validator больше не работает
В v2 его заменили на @field_validator (поле) и @model_validator (вся модель). Старый декоратор ещё импортируется, но помечен устаревшим — новый код пишите на новом синтаксисе.
.dict() и .json() пропали
В v2 используйте model_dump() и model_dump_json(). Поведение то же, имена приведены в соответствие с моделью.
Конфигурация через класс Config не работает
В v2 настройки задаются через model_config = ConfigDict(...), например model_config = ConfigDict(strict=True) — для запрета приведения типов.
Что дальше
Главное применение pydantic — FastAPI: там модели валидируют входные данные до вашего кода. Разбор — урок про модели Pydantic в FastAPI, а размышляете, что учить дальше для веба — честное сравнение FastAPI и Flask.
Прочитать данные из файлов и провалидировать их в модель — типовая связка: чтение CSV и Excel в pandas покажет, как данные попадают в DataFrame.