🐛 Частые ошибки Django-блока

🎯 Топ ошибок уроков 13–17 К оглавлению урока

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

  1. Приложение не в INSTALLED_APPS — миграции не создаются, модели не видны.
  2. Новое поле без null/default — Django не может применить миграцию к существующим записям.
  3. makemigrations без migrate — файл миграции создан, но изменения не применены к БД.

Ошибки при создании проекта и приложений

Ошибка 1: Приложение не зарегистрировано в INSTALLED_APPS

Симптом: python manage.py makemigrations пишет «No changes detected», хотя модели были изменены. Admin не показывает модели.

Причина: Приложение создано командой startapp, но не добавлено в INSTALLED_APPS.

# Неправильно: приложение есть, но Django о нём не знает
INSTALLED_APPS = [
    'django.contrib.admin',
    ...
]  # myapp отсутствует

# Правильно:
INSTALLED_APPS = [
    'django.contrib.admin',
    ...
    'myapp.apps.MyappConfig',  # Добавлено
]

Ошибка 2: SECRET_KEY в коде репозитория

Симптом: Реальный SECRET_KEY виден в git-истории. При компрометации злоумышленник может подделать сессии и CSRF-токены.

Правило: Никогда не коммитить настоящий SECRET_KEY. Использовать .env + .gitignore.

# .gitignore — добавить обязательно
.env
*.pyc
__pycache__/
db.sqlite3

Ошибки в моделях

Ошибка 3: Новое поле без null=True или default

Симптом: При makemigrations Django спрашивает «Provide a one-off default». Если принудительно применить — IntegrityError в БД.

# Неправильно — существующие записи получат NULL (но поле NOT NULL)
class Book(models.Model):
    title = models.CharField(max_length=200)
    rating = models.IntegerField()  # Добавлено без default

# Правильно — указать значение по умолчанию
class Book(models.Model):
    title = models.CharField(max_length=200)
    rating = models.IntegerField(default=0)  # OK
    # или: null=True для необязательных числовых полей

Ошибка 4: Путаница null и blank для строковых полей

Симптом: Форма принимает пустую строку, но в БД попадает пустая строка (""), а не NULL. Или наоборот.

# Для строковых полей — обычно оба
optional_name = models.CharField(max_length=100, blank=True, null=True)

# Для числовых и дат — только null
optional_age = models.IntegerField(null=True)

# Плохо: только blank без null для числового поля
age = models.IntegerField(blank=True)  # blank=True на числовых — почти не используется

Ошибка 5: CharField без max_length

Симптом: SystemCheckError: ERRORS: myapp.Book.title: (fields.E120) CharField does not define a 'max_length' attribute.

# Неправильно
title = models.CharField()  # max_length обязателен!

# Правильно
title = models.CharField(max_length=200)

Ошибки с миграциями

Ошибка 6: makemigrations без migrate

Симптом: Файл миграции создан в папке migrations/, но в БД изменений нет. Сервер выдаёт предупреждение «You have N unapplied migration(s)».

Правило: После makemigrations всегда выполнять migrate.

python manage.py makemigrations  # 1. Создать
python manage.py migrate         # 2. Применить — обязательно!

Ошибка 7: Редактирование файлов миграций вручную

Симптом: После ручного редактирования migrations/*.py при следующем migrate возникают конфликты или InconsistentMigrationHistory.

Правило: Не редактировать файлы миграций вручную без понимания последствий. Для исправления — создать новую миграцию.

Ошибки в Admin

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

Симптом: Модель создана и применена через миграцию, но в /admin/ не отображается.

# admin.py — не забыть добавить!
from django.contrib import admin
from .models import MyModel

admin.site.register(MyModel)  # Без этой строки — модель не видна в admin

Ошибка 9: Попытка войти в /admin/ без createsuperuser

Симптом: Форма входа в /admin/ выдаёт «Please enter the correct username and password».

Решение: Создать суперпользователя командой python manage.py createsuperuser. Обычные пользователи не имеют доступа к admin.

Ошибки со связями

Ошибка 10: ForeignKey без on_delete

Симптом: TypeError: __init__() missing 1 required positional argument: 'on_delete'

# Неправильно — on_delete обязателен с Django 2.0
author = models.ForeignKey(Author)  # Ошибка!

# Правильно
author = models.ForeignKey(Author, on_delete=models.CASCADE)

Ошибка 11: Циклический импорт при связях

Симптом: ImportError или AppRegistryNotReady при импорте моделей из разных приложений.

Решение: Использовать строку вместо класса в ForeignKey:

# Если Book в другом приложении 'library'
author = models.ForeignKey('library.Book', on_delete=models.CASCADE)
# Строка 'app.ModelName' — Django сам разрешит зависимость