Pydantic V2: Забываем root_validator, используем model_validator правильно Переход на Pydantic V2, это не только ускорение за счет ядра на Rust, но и …
Переход на Pydantic V2, это не только ускорение за счет ядра на Rust, но и переосмысление валидации.
Самая частая боль при миграции, проверка зависимостей между несколькими полями.
В V1 мы использовали root_validator и работали со словарем values (прощай, автодополнение IDE).
В V2 правильный путь - model_validator в режиме after.
В чем соль?
В режиме mode='after' валидация запускается после того, как поля были распаршены и приведены к типам.
Вы работаете с экземпляром класса (self), а не с сырым словарем.
Пример (валидация периода дат):
from pydantic import BaseModel, model_validator
from datetime import datetime
class DateRange(BaseModel):
start_dt: datetime
end_dt: datetime
@model_validator(mode='after')
def check_dates_order(self):
# Обращаемся через self — IDE видит поля и их типы!
if self.end_dt <= self.start_dt:
raise ValueError("Дата окончания должна быть позже начала")
return self
# Тест
try:
DateRange(
start_dt="2024-01-01T12:00:00",
end_dt="2023-01-01T12:00:00"
)
except ValueError as e:
print(e)
Нюансы для профи:
1. mode='before': Используйте только если вам нужно модифицировать сырые входные данные (например, JSON)
до того, как Pydantic начнет их парсить. Это аналог pre=True из V1.
2. Производительность: Валидаторы на Python, это узкое горлышко. Если у вас HighLoad, старайтесь выразить
ограничения через Field (например, ge, le), так как они отрабатывают на Rust-уровне, что значительно
быстрее вызова python-функции.
Используйте возможности типизации на 100%.
#pydantic #fastapi #bestpractices #python
👉 @BookPython