🐛 Типичные ошибки: Agile Projects ч.2
⚡ Топ-6 ошибок
- validate_* внутри Meta — DRF не вызывает их, валидация не работает
- Нет AUTH_USER_MODEL — миграции для кастомного User упадут
- make_aware на aware datetime — RuntimeError в DRF 3.15+
- Опечатка CreateTasSerializer — NameError, POST не работает
- file.split('.') вместо rsplit — ValueError при имени "file.report.pdf"
- Не пересоздана БД после кастомного User — конфликт схем, миграция не проходит
Ошибка 1: validate_* методы внутри class Meta
Симптом: Поля не валидируются — можно передать строку длиной 1 символ вместо 10, и ошибки нет.
Неправильно (из лекции):
class CreateTaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = (...)
# ❌ Внутри Meta — эти методы НИКОГДА не вызываются DRF
def validate_name(self, value):
if len(value) < 10:
raise serializers.ValidationError("Too short")
return value
Правильно:
class CreateTaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = (...)
# ✅ На уровне класса сериализатора
def validate_name(self, value: str) -> str:
if len(value) < 10:
raise serializers.ValidationError("Too short — min 10 characters")
return value
Объяснение: DRF ищет методы validate_<field> через интроспекцию класса сериализатора. Вложение в Meta делает их атрибутами вложенного класса, а не самого сериализатора.
Ошибка 2: Нет AUTH_USER_MODEL в settings.py
Симптом: django.db.migrations.exceptions.InconsistentMigrationHistory или ValueError: Related model 'users.User' cannot be resolved.
Неправильно:
# settings.py — только INSTALLED_APPS, без AUTH_USER_MODEL
INSTALLED_APPS = [
...
'apps.users.apps.UsersConfig',
]
# AUTH_USER_MODEL не указан → Django использует встроенный auth.User
Правильно:
# settings.py
AUTH_USER_MODEL = 'users.User' # ✅ обязательно до первой миграции
INSTALLED_APPS = [
...
'apps.users.apps.UsersConfig',
]
Объяснение: Если AUTH_USER_MODEL не задан до создания миграций, Django создаёт таблицы с auth.User. После смены на кастомного — конфликт. Нужно удалить БД и все миграции, потом пересоздать.
Ошибка 3: make_aware на already-aware datetime (DRF 3.15+)
Симптом: ValueError: Not naive datetime или RuntimeError: Cannot use make_aware on timezone-aware value.
Неправильно (из лекции):
def validate_deadline(self, value):
# ❌ DRF 3.15+ парсит datetime как aware — повторный make_aware упадёт
value = timezone.make_aware(value, timezone.get_current_timezone())
if value < timezone.now():
raise serializers.ValidationError("Cannot be in the past")
return value
Правильно:
def validate_deadline(self, value):
# ✅ Проверяем is_naive перед make_aware
if timezone.is_naive(value):
value = timezone.make_aware(value, timezone.get_current_timezone())
if value < timezone.now():
raise serializers.ValidationError("The deadline cannot be in the past")
return value
Ошибка 4: Опечатка CreateTasSerializer (без k)
Симптом: NameError: name 'CreateTasSerializer' is not defined. POST-запросы не работают.
# ❌ Из лекции — опечатка
serializer = CreateTasSerializer(data=request.data)
# ✅ Правильно
serializer = CreateTaskSerializer(data=request.data)
Ошибка 5: file_name.split('.') при нескольких точках
Симптом: ValueError: too many values to unpack при имени файла типа "my.quarterly.report.pdf".
# ❌ Из лекции
new_file_name, file_ext = file_name.split('.') # упадёт при "a.b.c"
# ✅ rsplit с maxsplit=1
stem, ext = file_name.rsplit('.', 1) # всегда ровно 2 части
Ошибка 6: Не пересоздана БД после добавления кастомного User
Симптом: django.db.utils.OperationalError: no such table: users_user или конфликт схем.
Правильный порядок действий:
# 1. Удалить базу
del db.sqlite3
# 2. Удалить все migration-файлы (кроме __init__.py) из каждого приложения
# apps/tasks/migrations/*.py (кроме __init__)
# apps/projects/migrations/*.py
# apps/users/migrations/*.py
# 3. Добавить в settings.py
AUTH_USER_MODEL = 'users.User'
# 4. Заново создать и применить миграции
python manage.py makemigrations
python manage.py migrate
# 5. Создать суперпользователя
python manage.py createsuperuser
Предупреждение: deleted=True по умолчанию
Симптом: Все новые пользователи помечены как «удалённые» сразу после создания.
# ❌ Из лекции — логическая ошибка
deleted = models.BooleanField(default=True) # все = удалены?
# ✅ Правильно
deleted = models.BooleanField(default=False) # не удалён