Когда вычисляются наборы запросов QuerySet
Создание набора запросов QuerySet не требует каких-либо действий с базой данных до тех пор, пока он не будет вычислен.
Наборы запросов обычно возвращают еще один не вычисленный набор запросов.
В наборе запросов можно конкатенировать столько фильтров, сколько потребуется, и база данных не будет затронута до тех пор, пока набор запросов не будет вычислен.
При вычислении набора запросов он конвертируется в запрос на языке SQL к базе данных.
Наборы запросов QuerySet вычисляются только в следующих ниже случаях:
-
при первом их прокручивании в цикле;
-
при их нарезке, например
Post.objects.all()[:3]; -
при их консервации в поток байтов или кешировании;
-
при вызове на них функций
repr()илиlen(); -
при вызове на них функции
list()в явной форме; -
при их проверке в операциях
bool(),or,and,if.
Создание модельных менеджеров
По умолчанию в каждой модели используется менеджер objects. Этот менеджер извлекает все объекты из базы данных. Однако имеется возможность определять конкретно-прикладные модельные менеджеры.
Давайте создадим конкретно-прикладной менеджер,чтобы извлекать все посты, имеющие статус PUBLISHED.
Есть два способа добавлять или адаптировать модельные менеджеры под конкретно-прикладную задачу:
можно добавлять дополнительные методы менеджера в существующий менеджер,
либо создавать новый менеджер, видоизменив изначальный набор запросов QuerySet, возвращаемый менеджером.
Первый метод предоставляет обозначение набора запросов в виде Post.objects.my_manager(), а второй предоставляет обозначение набора запросов в виде Post.my_manager.all().
Мы выберем второй метод, чтобы реализовать менеджер, который позволит извлекать посты, используя обозначение Post.published.all().
Отредактируйте файл models.py приложения blog, добавив конкретно-прикладной менеджер, как показано ниже:
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset()\
.filter(status=Post.Status.PUBLISHED)
class Post(models.Model):
# поля модели....
objects = models.Manager() # менеджер, применяемый по умолчанию
published = PublishedManager() # конкретно-прикладной менеджер
class Meta:
ordering = ['-publish']
indexes = [
models.Index(fields=['-publish']),
]
def __str__(self):
return self.title
Первый объявленный в модели менеджер становится менеджером, который используется по умолчанию.
Для того чтобы указать другой такой менеджер, применяется Meta-атрибут default_manager_name.
Если менеджер в модели не определен, то Django автоматически создает для нее стандартный менеджер objects.
Если в своей модели вы объявляете какие-либо менеджеры, но также хотите сохранить менеджер objects, то вы должны добавить его в свою модель явным образом.
В приведенном выше исходном коде мы добавили в модель Post стандартный менеджер objects и конкретно-прикладной менеджер published.
Метод get_queryset() менеджера возвращает набор запросов QuerySet, который будет исполнен. Мы переопределили этот метод, чтобы сформировать конкретно-прикладной набор запросов QuerySet, фильтрующий посты по их статусу и возвращающий поочередный набор запросов QuerySet, содержащий посты только со статусом PUBLISHED.
Теперь, когда мы определили для модели Post конкретно-прикладной менеджер, давайте его протестируем!
Следующей ниже командой снова запустите сервер разработки из командной оболочки:
python manage.py shell
Теперь можно импортировать модель Post и извлечь все опубликованные посты, заголовки которых начинаются с Как, исполнив следующий ниже набор запросов QuerySet:
from blog.models import Post
Post.published.filter(title__startswith='Как')
Для того чтобы получить результаты этого набора запросов, проверьте, чтобы поле status было равным значению PUBLISHED в объекте Post, поле title которого начинается со слова Как: