🐛 Типичные ошибки практикума

Что идёт не так и как это исправить

⚡ Топ-7 ошибок

  1. Забыть on_delete в ForeignKey — TypeError при миграции
  2. Поле choices: значение не совпадает с ключом — фильтр/поиск не работает
  3. ManyToManyField в list_display напрямую — ImproperlyConfigured
  4. null=True у ManyToManyField — Django игнорирует, выдаёт warning
  5. Admin-действие не добавлено в список actions — действие не появляется в меню
  6. Fixtures: пользователи загружаются раньше групп — IntegrityError
  7. Пользователь без is_staff=True не попадает в Admin

Ошибка 1: Забыть on_delete в ForeignKey

Ошибка:
project = models.ForeignKey(Project)  # TypeError!

Django требует явного указания on_delete с Django 2.0+. Без него миграция не выполнится.

Исправление:
project = models.ForeignKey(Project, on_delete=models.CASCADE)

Ошибка 2: Несоответствие ключа choices и значения по умолчанию

Ошибка:
STATUSES_CHOICES = [('new', 'New'), ...]
status = models.CharField(choices=STATUSES_CHOICES, default='New')
# default='New' не совпадает с ключом 'new'!
Исправление:
STATUSES_CHOICES = [('New', 'New'), ...]
status = models.CharField(choices=STATUSES_CHOICES, default='New')
# ключ и default должны совпадать

Ошибка 3: ManyToManyField напрямую в list_display

Ошибка:
@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
    list_display = ['title', 'tags']  # ImproperlyConfigured!

Django не может отобразить M2M-поле как колонку — нет единственного значения.

Исправление:
@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
    list_display = ['title', 'display_tags']

    def display_tags(self, obj):
        return ', '.join(tag.name for tag in obj.tags.all())
    display_tags.short_description = 'Tags'

Ошибка 4: null=True у ManyToManyField

Ошибка:
tags = models.ManyToManyField('Tag', null=True, blank=True)

Django выдаёт SystemCheck warning: WARNINGS: myapp.Task.tags: (fields.W340) null has no effect on ManyToManyField.

Исправление:
tags = models.ManyToManyField('Tag', blank=True)

Ошибка 5: Admin-действие не зарегистрировано в actions

Ошибка:
class ProjectAdmin(admin.ModelAdmin):
    def replace_spaces_with_underscores(self, request, objects):
        ...
    # забыли actions = [...]!
Исправление:
class ProjectAdmin(admin.ModelAdmin):
    actions = ['replace_spaces_with_underscores']  # обязательно!

    def replace_spaces_with_underscores(self, request, objects):
        ...

Ошибка 6: Fixtures — неверный порядок loaddata

Ошибка:
# Загружаем пользователей РАНЬШЕ групп
python manage.py loaddata users_fixture.json   # IntegrityError!
python manage.py loaddata groups_fixture.json

Пользователи ссылаются на группы через ForeignKey. Если группы ещё не созданы — IntegrityError.

Исправление:
# Сначала группы, потом пользователи
python manage.py loaddata groups_fixture.json
python manage.py loaddata users_fixture.json

Ошибка 7: Пользователь без is_staff не входит в Admin

Ошибка: создан пользователь, добавлена группа Client, но при попытке открыть /admin/ — перенаправление на страницу входа или сообщение "You don't have permission".
Исправление:

В Admin → Users → редактировать пользователя → поставить галочку "Staff status" (is_staff=True). Только пользователи с is_staff=True могут войти в Admin-панель.

Ошибка 8: unique_together с неверными полями

Ошибка:
class Meta:
    unique_together = ('name', 'created_at')  # кортеж, не кортеж кортежей
Исправление:
class Meta:
    unique_together = (('name', 'created_at'),)  # кортеж из кортежей!

Ошибка 9: FileField без MEDIA_ROOT

Ошибка:
file = models.FileField(upload_to='projects/')

Файлы загружаются, но в неожиданное место или выдают ошибку при разработке.

Исправление: добавить в settings.py:
import os

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

И в urls.py добавить обслуживание медиафайлов при DEBUG=True.