🐛 Типичные ошибки

🎯 Частые ловушки при работе с Pydantic

Ошибка 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