Ответ
Объект QuerySet в Django представляет собой коллекцию объектов из базы данных. Его ключевая особенность — ленивость (laziness): запрос к базе данных выполняется только в момент реального обращения к данным (например, в цикле или при вызове list()).
Основные методы можно разделить на две категории:
1. Методы, возвращающие новый QuerySet (не выполняют запрос к БД)
Эти методы можно выстраивать в цепочки для создания сложных запросов.
filter(**kwargs): ВозвращаетQuerySet, содержащий объекты, которые соответствуют заданным параметрам поиска.exclude(**kwargs): ВозвращаетQuerySet, исключающий объекты, которые соответствуют параметрам.order_by(*fields): СортируетQuerySetпо указанным полям. Префикс-означает сортировку по убыванию (например,'-created_at').annotate(**kwargs): Добавляет к каждому объекту вQuerySetвычисляемое поле (например, с помощью агрегатных функцийCount,Sum).values(*fields): ВозвращаетQuerySet, который при итерации выдает словари, а не объекты моделей.all(): Возвращает копию текущегоQuerySet.
2. Методы, выполняющие запрос к БД (возвращают данные)
Эти методы вызывают обращение к базе данных и возвращают конкретный результат.
get(**kwargs): Возвращает один-единственный объект. Если найдено 0 или более 1 объекта, вызывает исключение (DoesNotExistилиMultipleObjectsReturned).count(): Возвращает количество объектов вQuerySet.first()/last(): Возвращают первый/последний объект вQuerySetилиNone, если он пуст.exists(): ВозвращаетTrue, еслиQuerySetсодержит хотя бы один объект, иначеFalse. Более эффективен, чемcount() > 0.
Пример цепочки вызовов:
from django.db.models import Count
from .models import Post
# Найти 10 самых популярных постов в категории 'Python',
# опубликованных в этом году, отсортированных по количеству комментариев
popular_posts = (
Post.objects
.filter(category__name='Python', pub_date__year=2023) # Фильтрация
.annotate(num_comments=Count('comments')) # Добавление вычисляемого поля
.order_by('-num_comments') # Сортировка по убыванию
[:10] # Ограничение выборки (срез)
)
# Запрос к БД будет выполнен только здесь, при итерации
for post in popular_posts:
print(f'{post.title} - Комментариев: {post.num_comments}')