🐛 Типичные ошибки
Ошибка 1. Используешь @validator вместо @field_validator
Симптом: код падает с ошибкой NameError: name 'validator' is not defined или работает некорректно.
Причина: в Pydantic v2 декоратор называется @field_validator, а не @validator (как в v1).
# ❌ Неправильно (v1)
from pydantic import validator
# ✅ Правильно (v2)
from pydantic import field_validator
Ошибка 2. Используешь методы v1 в v2
Симптом: AttributeError: 'User' object has no attribute 'dict'.
Причина: в Pydantic v2 методы переименованы.
# ❌ Неправильно (v1)
user.dict()
user.json()
User.parse_raw(json_str)
# ✅ Правильно (v2)
user.model_dump()
user.model_dump_json()
User.model_validate_json(json_str)
Ошибка 3. Забыл установить pydantic[email]
Симптом: ImportError: email-validator is not installed при использовании EmailStr.
Решение:
pip install pydantic[email]
Ошибка 4. Неправильно используешь Ellipsis
Симптом: поле не считается обязательным или вызывает путаницу.
Причина: в Pydantic v2 поле без значения по умолчанию и без = Field(...) всё равно обязательное. Ellipsis нужен только внутри Field() для явности.
# ✅ Обязательное поле (без Ellipsis тоже работает)
name: str
# ✅ Явное указание обязательности внутри Field
name: str = Field(..., min_length=2)
Ошибка 5. Забываешь mode='after' в model_validator
Симптом: model_validator не работает как ожидается, или Pydantic ругается на сигнатуру.
Решение: в Pydantic v2 нужно явно указать режим:
@model_validator(mode='after')
def check_something(self):
...
Ошибка 6. Путаешь ge и gt
Симптом: валидация пропускает 0, когда ожидалось, что 0 будет отклонено.
# ❌ Принимает 0 (greater or equal)
price: float = Field(ge=0)
# ✅ Отклоняет 0 (greater than)
price: float = Field(gt=0)
Ошибка 7. Изменяешь поле модели напрямую без validate_assignment
Симптом: присваивание некорректного значения полю не вызывает ошибку.
# Без настройки — присваивание не валидируется
user.age = "not_a_number" # Пройдёт молча!
# ✅ С validate_assignment (Pydantic v2)
from pydantic import BaseModel, ConfigDict
class User(BaseModel):
model_config = ConfigDict(validate_assignment=True)
age: int