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

Ошибки, которые встречаются при выполнении практикума

⚡ Топ-5 ошибок практикума

  1. NameError: опечатка в имени переменной (task_to_updated вместо task_to_update)
  2. ImportError: Q или F не импортированы перед использованием
  3. update() vs save(): .update() — на QuerySet, .save() — на объекте
  4. Потеря переменных в shell: новая сессия — нет объектов из прошлой
  5. User.objects.create() с паролем: пароль не хэшируется — используйте create_user()

← К оглавлению урока

Ошибка 1: Опечатка в имени переменной (NameError)

Из источника лекции (задание 14):

# Неправильно — NameError: name 'task_to_updated' is not defined
task_to_update = Task.objects.filter(name='Update schema')
task_to_updated.update(status='pending')  # опечатка!
# Правильно
task_to_update = Task.objects.filter(name='Update schema')
task_to_update.update(status='pending')

Симптом: NameError: name 'task_to_updated' is not defined

Причина: переменная называется task_to_update, а вызов идёт на task_to_updated (лишняя буква d).

Ошибка 2: Не импортированы Q или F

# Неправильно — NameError: name 'Q' is not defined
Task.objects.filter(Q(status='new') | Q(priority='Urgent'))
# Правильно — сначала импорт
from django.db.models import Q, F

Task.objects.filter(Q(status='new') | Q(priority='Urgent'))

Симптом: NameError: name 'Q' is not defined

Ошибка 3: Путаница .update() на QuerySet vs .save() на объекте

# Неправильно — AttributeError: 'Task' object has no attribute 'update'
task = Task.objects.get(name='Update schema')
task.update(status='pending')  # объект, не QuerySet!
# Вариант А: .update() — на QuerySet
Task.objects.filter(name='Update schema').update(status='pending')

# Вариант Б: .save() — на объекте
task = Task.objects.get(name='Update schema')
task.status = 'pending'
task.save()

Ошибка 4: Потеря переменных в shell при перезапуске

# Новая сессия shell — переменные tiger_project, backend_dev и т.д. отсутствуют
tiger_task_1.tags.add(back_tag)
# NameError: name 'tiger_task_1' is not defined
# Получаем объекты из БД заново
tiger_project = Project.objects.get(name='TIGER')
backend_dev = User.objects.get(username='backend_dev')
back_tag = Tag.objects.get(name='Backend')
tiger_task_1 = Task.objects.get(name="Create new endpoint to get all project's tasks")

Совет: при работе с последовательными задачами не закрывайте shell-сессию. Если закрыли — восстановите переменные через .get() или .filter().

Ошибка 5: create() vs create_user() для пользователей

# Неправильно для production — пароль сохраняется в открытом виде
User.objects.create(username='user1', password='secret123')
# Правильно — create_user() хэширует пароль
User.objects.create_user(
    username='user1',
    password='secret123',
    email='user@example.com'
)

Последствие: при create() пароль попадает в БД в открытом виде (plain text), и user.check_password() будет всегда возвращать False. Аутентификация не будет работать.

Ошибка 6: distinct() при фильтрации через M2M или IN

# Без distinct() — дублирующиеся проекты если у них несколько подходящих файлов
projects = Project.objects.filter(project_files__in=recent_files)
# Правильно
projects = Project.objects.filter(
    project_files__in=recent_files
).distinct()

Симптом: один проект появляется в результате несколько раз (по числу совпавших файлов).

Ошибка 7: bulk_update без передачи списка полей

# Неправильно — TypeError: bulk_update() missing 1 required positional argument: 'fields'
Task.objects.bulk_update(tasks_to_update)
# Правильно — обязательно указать список обновляемых полей
Task.objects.bulk_update(tasks_to_update, ['status'])
Task.objects.bulk_update(tasks_to_update, ['status', 'due_date'])

Ошибка 8: Неправильный порядок аргументов в filter() с Q и kwargs

# Неправильно — Q-аргументы ПОСЛЕ kwargs вызывают SyntaxError или неожиданный результат
Task.objects.filter(due_date__lte=end_of_month, Q(priority='Critical'))
# Правильно — kwargs после Q-аргументов, или все в Q
Task.objects.filter(
    Q(priority='Critical') | Q(priority='Urgent'),
    due_date__lte=end_of_month
)

Правило: kwargs в filter() применяются как AND. Q-объекты можно смешивать с kwargs, но Q-объекты должны идти первыми.

← К оглавлению урока