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

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

  1. Не определить __str__ — объекты отображаются как "Book object (1)"
  2. Использовать unique_together вместо UniqueConstraint (deprecated)
  3. Не зарегистрировать модель в admin.py — она не видна в Admin

Ошибка 1: Не определён метод __str__

Симптом: в Admin и shell объекты отображаются как Book object (1), Book object (2) — неинформативно.

# Неправильно — нет __str__
class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.CharField(max_length=100)
# Правильно
class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.CharField(max_length=100)

    def __str__(self):
        return f"{self.title} by {self.author}"

Ошибка 2: Использование deprecated unique_together

Симптом: код работает, но в Django 4.2+ появляются предупреждения. В будущих версиях может быть удалён.

# Устарело (из лекции)
class Meta:
    unique_together = ('title', 'author')
# Современный способ (Django 4.2+)
from django.db.models import UniqueConstraint

class Meta:
    constraints = [
        UniqueConstraint(
            fields=['title', 'author'],
            name='unique_title_author'
        ),
    ]

Ошибка 3: Модель не зарегистрирована в admin.py

Симптом: модель есть в базе данных, но в Admin-панели её не видно.

# Ошибка — забыли зарегистрировать
# admin.py пустой или модель не добавлена
# Правильно
from django.contrib import admin
from .models import Book

@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'published_date')

Ошибка 4: search_fields с FK без указания поля

Симптом: ошибка TypeError: Related Field got invalid lookup: icontains или неожиданный результат поиска.

# Неправильно — author это ForeignKey, нельзя искать по объекту
search_fields = ('title', 'author')
# Правильно — указываем конкретное поле через __
search_fields = ('title', 'author__name')

Ошибка 5: Два способа регистрации одновременно

Симптом: ошибка AlreadyRegistered: The model Book is already registered in app 'library'.

# Ошибка — модель зарегистрирована дважды
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ('title',)

admin.site.register(Book)  # AlreadyRegistered!
# Правильно — выбрать один способ
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ('title',)

Ошибка 6: verbose_name в ModelAdmin вместо Meta

Симптом: verbose_name не влияет на отображение, потому что это не атрибут ModelAdmin.

# Ошибка — verbose_name здесь не работает
class BookAdmin(admin.ModelAdmin):
    verbose_name = 'Книга'  # Это не атрибут ModelAdmin!
# Правильно — verbose_name в классе Meta модели
class Book(models.Model):
    ...
    class Meta:
        verbose_name = 'Книга'
        verbose_name_plural = 'Книги'

Ошибка 7: Изменение db_table после первой миграции

Симптом: Django создаёт новую таблицу и не переносит данные из старой. Данные теряются!

# Опасно — менять db_table у существующей модели
class Meta:
    db_table = 'new_table_name'  # Если была 'old_name' — данные не переносятся

Правило: задавайте db_table только при создании модели. Если нужно переименовать — используйте RunSQL в миграции для явного переноса данных.

Ошибка 8: Отсутствие миграции после изменения Meta

Симптом: изменения в Meta (ordering, verbose_name) не применяются.

Некоторые изменения Meta (например, ordering, verbose_name) требуют миграции, хотя не меняют структуру таблицы. После любых изменений в модели нужно:

python manage.py makemigrations
python manage.py migrate