🐛 Частые ошибки Django-блока
⚡ Топ-3 ошибки
- get() без try/except — всегда оборачивай в try/except DoesNotExist.
- AUTH_USER_MODEL после миграции — кастомный User нужно прописать ДО первой миграции.
- Нет makemigrations после изменения модели — изменения в models.py не применяются без миграций.
1. get() без обработки исключений
Проблема
# Опасно — упадёт при отсутствии записи
book = Book.objects.get(title="The Great Gatsby")
Решение
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
try:
book = Book.objects.get(title="The Great Gatsby")
except ObjectDoesNotExist:
book = None
print("Книга не найдена")
except MultipleObjectsReturned:
book = Book.objects.filter(title="The Great Gatsby").first()
print("Несколько книг, берём первую")
2. AUTH_USER_MODEL прописан после первой миграции
Проблема
Разработчик создаёт кастомный User и прописывает AUTH_USER_MODEL после того, как уже выполнил migrate. Результат — конфликты между auth-таблицами, невозможность применить миграции.
Решение
Всегда создавай CustomUser и прописывай AUTH_USER_MODEL до первой миграции. Если уже есть данные — нужно пересоздать БД или использовать сложные миграции.
# settings.py — до первой миграции
AUTH_USER_MODEL = 'myapp.CustomUser'
# После этого:
python manage.py makemigrations
python manage.py migrate
3. Забыли выполнить makemigrations после изменения модели
Проблема
Добавили поле в модель, но не запустили makemigrations. Django продолжает работать со старой схемой БД. Ошибка появляется в рантайме при попытке обращения к новому полю.
Решение
# После каждого изменения модели
python manage.py makemigrations
python manage.py migrate
# Проверка состояния
python manage.py showmigrations
4. Добавление поля без null=True или default
Проблема
При добавлении нового поля к модели с существующими данными Django не знает, какое значение записать в уже существующие строки. makemigrations зависнет в интерактивном режиме или упадёт.
# Проблема — нет default и null=True
class Book(models.Model):
rating = models.FloatField() # существующие записи?
Решение
# Указать default или null=True
class Book(models.Model):
rating = models.FloatField(null=True, blank=True)
# или
rating = models.FloatField(default=0.0)
5. index_together вместо indexes (устарело)
Проблема
class Meta:
index_together = ('title', 'author') # deprecated в Django 4.2
Решение
class Meta:
indexes = [
models.Index(fields=['title', 'author']),
]
6. Зарегистрировать модель, не добавленную в INSTALLED_APPS
Проблема
Создаётся приложение, в admin.py регистрируется модель, но приложение не добавлено в INSTALLED_APPS. Django его игнорирует — модели не видны в admin.
Решение
# settings.py
INSTALLED_APPS = [
...
'myapp.apps.MyappConfig', # обязательно!
]
7. bulk_create не вызывает сигналы save
Проблема
Используется bulk_create, но в проекте есть логика в pre_save / post_save сигналах. Bulk-операции обходят сигналы Django.
Решение
Если нужны сигналы — используй обычный цикл с save(). Если сигналы не нужны (массовый импорт данных) — bulk_create правильный выбор.
8. N+1 проблема при обходе связанных объектов
Проблема
# Для каждой книги выполняется отдельный SQL-запрос к Publisher
books = Book.objects.all()
for book in books:
print(book.publisher.name) # N+1 запросов!
Решение
# select_related — JOIN для ForeignKey / OneToOneField
books = Book.objects.select_related('publisher').all()
for book in books:
print(book.publisher.name) # один запрос с JOIN
prefetch_related вместо select_related.