Вопрос: как перейти на Pydantic v2 и какие у него проблемы - Академия Selectel

Вопрос: как перейти на Pydantic v2 и какие у него проблемы

Линия поддержки
Линия поддержки Ответы на вопросы пользователей
1 апреля 2026

Показали, что ломается в Pydantic v2 чаще всего и как проверить код до релиза, чтобы не уронить API в продакшене.

Изображение записи

Комментарий пользователя

Здравствуйте! Обновили pydantic до 2.x, и теперь часть запросов от клиента сразу падает с 422‑ошибками. Вместо Optional стали падать «field required», root_validator не работает, а старые валидаторы вообще не видит. Можно ли как-то перейти на v2, не переписывая весь код сразу?

Никита Герич Пользователь

Ответ специалиста

Добрый день, Никита! Мы регулярно такое видим, особенно на таких сервисах как FastAPI, где много моделей и валидаторов. Во второй версии Pydantic поведение и правда поменялось, но почти все можно сделать по‑человечески. Рефакторинг не будет слишком болезненным.

  • Земцов Антон

    Земцов Антон

    Младший бэкенд-разработчик Python

Ниже привел примеры самого частого, что цепляет прод.

Optional. Он перестает означать «можно не передавать поле» — в v2 такой тип скорее означает «поле обязательно, но может быть None». Если клиент иногда пропускает поле в запросе, в v2 он может вдруг начать получать field required, просто потому что модель ожидает его наличия.

Валидаторы переехали. validator и root_validator из v1 в чистых v2‑моделях не работают, зато есть field_validator и model_validator(mode=”after”) — по сути те же функции, но с другим синтаксисом и чуть более строгой логикой.

Новые методы. model.dict(), parse_obj() и schema() почти полностью заменены на model.model_dump(), model.model_validate() и model.model_json_schema() — это уже норма для новых проектов.

По опыту, самый мягкий путь — это не пытаться в один день переключить весь код, а плавно переносить куски в v2‑стиль, а старые части оставить в pydantic.v1. Так вы не уроните прод, пока тестируете новое поведение.

Вот как может выглядеть переход одной простой модели:


      from typing import Optional
from pydantic import BaseModel, field_validator, model_validator, ConfigDict
from typing_extensions import Self

Было в v1:


      """
from pydantic import BaseModel, validator, root_validator

class UserIn(BaseModel):
    name: str
    email: Optional[str]
    age: int

    @validator("email")
    def ensure_email(cls, v):
        if v and "@" not in v:
            raise ValueError("Invalid email")
        return v

    @root_validator
    def ensure_age_positive(cls, values):
        if values.get("age", 0) < 0:
            raise ValueError("Age must be positive")
        return values
"""

 Стало в v2:


      class UserIn(BaseModel):
    model_config = ConfigDict(
        ser_json_timedelta="iso8601",
        extra="forbid",
    )

    name: str
    email: Optional[str] = None  # теперь можно честно не передавать
    age: int

    @field_validator("email")
    @classmethod
    def validate_email(cls, v: Optional[str]) -> Optional[str]:
        if v is not None and "@" not in v:
            raise ValueError("Invalid email")
        return v

    @model_validator(mode="after")
    def validate_age_positive(self) -> Self:
        if self.age < 0:
            raise ValueError("Age must be positive")
        return self

Теперь:

  • email можно спокойно не передавать в JSON;
  • model_validator срабатывает уже после валидации полей;
  • в контроллерах используете model.model_validate() и model.model_dump() вместо старых вызовов — это уже привычный паттерн в FastAPI‑проектах.

Если у вас уже есть v1‑слой в проекте, он не сломается сам по себе при обновлении, но это временная мера, пока не сделан ручной или автоматический перенос. Автоматизировать часть миграции можно, например, через bump‑pydantic — он сам переписывает большую часть методов, а вы уже смотрите diff и доводите код до порядка.

Раскатывать изменения лучше постепенно через feature-флаги, переключая на v2-модели по одному роуту. При старте сервиса полезно выводить в лог model_json_schema(), чтобы сразу увидеть, не разъехалась ли схема с тем, что ждет фронтенд.

В K8s на время миграции стоит накинуть лимитов по CPU и памяти. Хоть v2 и быстрее, при смешанном коде нагрузка может скакать, так что лучше перестраховаться.

Оставайтесь на связи с актуальным стеком. А за порцией вдохновения и советов приходите в Академию Selectel.