Короткий ответ
QuerySet — высокоуровневый API Django для получения, фильтрации и обработки объектов модели; его возвращают методы менеджера вроде Model.objects.all() и Model.objects.filter(). Главное свойство QuerySet — ленивость: запрос к базе выполняется только когда данные действительно нужны.
Как это работает подробнее
Ленивость позволяет накапливать условия фильтрации и получать ровно один оптимизированный запрос в момент обращения к данным.
- Момент выполнения. Запрос уходит в базу при итерации, срезе, преобразовании в список, проверке булева значения или вызове len().
- Цепочки. Методы filter(), exclude() и order_by() вызываются друг за другом, уточняя итоговую выборку.
- Переиспользование. Один и тот же QuerySet можно уточнять дальше, не выполняя лишних запросов к БД.
- Оптимизация связей. Число запросов к связанным объектам сокращают методы select_related() и prefetch_related().
Пример кода
Ленивая выборка QuerySet
# QuerySet не обращается к БД, пока данные не понадобятся
active_users = User.objects.filter(is_active=True)
for user in active_users: # запрос выполняется здесь, при итерации
print(user.username)Что использовать на практике
- Уточнение выборки. Строй цепочки filter(), exclude() и order_by() до обращения к данным.
- Проверка наличия. Используй .exists(), когда нужно лишь узнать, есть ли записи.
- Связи. Для ForeignKey применяй select_related(), для ManyToMany — prefetch_related().
Подводные камни
- Повторные запросы. Итерация по одному QuerySet несколько раз выполняет запрос заново: сохрани результат в список.
- Булева проверка. Приведение всего QuerySet к bool выполняет запрос; для проверки наличия лучше .exists().
- N+1 в циклах. Без select_related() и prefetch_related() обращение к связям в цикле плодит лишние запросы.
Как отвечать на собеседовании
- Дай определение QuerySet как коллекции объектов модели → объясни ленивость на примере: filter() не трогает базу, запрос идёт при итерации → покажи цепочки уточняющих методов → упомяни select_related() и prefetch_related() против N+1.