Ошибка 1: Приложение не в INSTALLED_APPS
Ошибка:
python manage.py makemigrations завершается с «No changes detected» даже после изменений в models.py.
Причина: Приложение library не зарегистрировано в settings.py.
Неправильно:
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
# library отсутствует!
]
Правильно:
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'library', # добавить!
]
Ошибка 2: ForeignKey без on_delete
Ошибка:
TypeError: __init__() missing 1 required positional argument: 'on_delete'
Неправильно:
author = models.ForeignKey(Author)
# Django 2.0+ требует on_delete
Правильно:
author = models.ForeignKey(
Author,
on_delete=models.SET_NULL,
null=True
)
Ошибка 3: SET_NULL без null=True
Ошибка:
django.db.utils.IntegrityError: NOT NULL constraint failed
Если используется on_delete=models.SET_NULL, поле в БД должно допускать NULL.
Неправильно:
author = models.ForeignKey(
Author,
on_delete=models.SET_NULL
# null=True отсутствует!
)
Правильно:
author = models.ForeignKey(
Author,
on_delete=models.SET_NULL,
null=True # обязательно!
)
Ошибка 4: Забыть применить миграции
Ошибка:
django.db.utils.OperationalError: no such column: library_author.profile
Причина: Поле добавлено в модель, но миграция не создана или не применена.
# Правильный порядок после изменения models.py:
python manage.py makemigrations # создать файл миграции
python manage.py migrate # применить к БД
Ошибка 5: default=timezone.now() с вызовом
Ошибка: Все записи получают одно и то же значение даты — дату запуска сервера.
Неправильно:
registration_date = models.DateField(
default=timezone.now() # вызов ()!
# Дата вычисляется один раз при старте
)
Правильно:
registration_date = models.DateField(
default=timezone.now # без ()
# Функция вызывается при создании объекта
)
Ошибка 6: null и blank — путаница
Это часто путают:
null=True— разрешает NULL в базе данных (SQL)blank=True— разрешает пустое значение в Django-формах и Admin
Только null=True:
profile = models.URLField(null=True)
# В БД: NULL разрешён
# В Admin: поле ОБЯЗАТЕЛЬНО к заполнению
# → форма не примет пустое значение!
null=True + blank=True:
profile = models.URLField(null=True, blank=True)
# В БД: NULL разрешён
# В Admin: поле можно оставить пустым
# → правильно для необязательных полей
Ошибка 7: Циклические зависимости в ForeignKey
Ошибка:
NameError: name 'Library' is not defined
Причина: Модель использует другую модель, которая определена ниже в файле.
Неправильно (Library не определена ещё):
class Member(models.Model):
libraries = models.ManyToManyField(
Library, # NameError!
related_name='members'
)
class Library(models.Model):
...
Правильно (строка с именем):
class Member(models.Model):
libraries = models.ManyToManyField(
'Library', # строка — ОК
related_name='members'
)
class Library(models.Model):
...
Ошибка 8: Validators не выполняются в shell
Важно:
MinValueValidator и MaxValueValidator срабатывают только при валидации форм или ручном вызове model.full_clean(). Прямое создание объекта в shell обходит валидаторы.
# Это НЕ вызовет ошибку (валидатор пропущен):
author = Author.objects.create(rating=999)
# Это вызовет ValidationError:
author = Author(rating=999)
author.full_clean() # явная проверка
author.save()
Ошибка 9: Удаление модели без миграции
Задача 9 предполагает удаление Publisher. Нельзя просто удалить класс из models.py — нужно создать миграцию.
# 1. Удалить класс Publisher из models.py
# 2. Изменить Book.publisher_id на ForeignKey(Member, ...)
# 3. Создать и применить миграцию:
python manage.py makemigrations
python manage.py migrate
Если в БД уже есть данные в таблице Publisher, Django предупредит о каскадном удалении данных. В разработке это нормально, в продакшн — нужно мигрировать данные вручную.