Короткий ответ
get() ожидает ровно одну подходящую строку и возвращает сам объект, выбрасывая DoesNotExist, если строк нет, или MultipleObjectsReturned, если найдено больше одной; filter().first() возвращает первый объект из QuerySet или None, без исключений при отсутствии совпадений.
Как это работает подробнее
get() выполняет тот же SQL-запрос, что и filter(), но проверяет количество строк и возвращает объект либо поднимает исключение; filter() всегда возвращает QuerySet, а .first()/.last() материализуют один объект или None.
Пример кода
example.py
from django.core.exceptions import ObjectDoesNotExist
try:
user = User.objects.get(email="alice@example.com")
except User.DoesNotExist:
user = None
except User.MultipleObjectsReturned:
raise RuntimeError("Email должен быть уникальным, но найдено несколько пользователей")
# Эквивалент без исключений:
user = User.objects.filter(email="alice@example.com").first()Что использовать на практике
- Практика. get() удобен, когда ожидается ровно одна запись (поиск по уникальному email); отсутствие/дублирование — ошибочная ситуация, которую стоит обработать явно. filter().first() уместен, когда отсутствие результата — нормальный случай.
Подводные камни
- Ошибка. Используют get() без обработки исключений в коде, который должен штатно работать с «не найдено», получая необработанный 500 вместо 404; забывают, что MultipleObjectsReturned возможен, если на уровне БД отсутствует реальное unique-ограничение.