Метод get_queryset
Метод get_queryset используется в кастомных менеджерах
для определения QuerySet, который будет возвращаться по
умолчанию при вызове менеджера модели. Этот метод часто
переопределяется для добавления фильтрации, сортировки или
других модификаций запросов на уровне менеджера.
Метод не принимает дополнительных аргументов и возвращает
экземпляр QuerySet.
Синтаксис
class CustomManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(condition)
Пример
Создадим кастомный менеджер, который по умолчанию возвращает только опубликованные статьи:
from django.db import models
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status="published")
class Article(models.Model):
title = models.CharField(max_length=200)
status = models.CharField(max_length=20)
created_at = models.DateTimeField(auto_now_add=True)
objects = models.Manager()
published = PublishedManager()
Теперь при обращении к менеджеру published будут
возвращаться только опубликованные статьи:
from myapp.models import Article
published_articles = Article.published.all()
print(published_articles)
Результат выполнения кода:
[<Article: First article>, <Article: Second article>]
Пример
Переопределим метод get_queryset для добавления
сортировки по умолчанию:
from django.db import models
class OrderedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().order_by("-created_at")
class Post(models.Model):
title = models.CharField(max_length=200)
created_at = models.DateTimeField(auto_now_add=True)
objects = OrderedManager()
При запросе всех записей они автоматически сортируются по дате создания в обратном порядке:
from myapp.models import Post
posts = Post.objects.all()
for post in posts:
print(post.title)
Результат выполнения кода:
"Newest post"
"Middle post"
"Oldest post"
Пример
Создадим менеджер, который исключает из выборки записи с определённым статусом:
from django.db import models
class ActiveManager(models.Manager):
def get_queryset(self):
return super().get_queryset().exclude(is_deleted=True)
class UserProfile(models.Model):
name = models.CharField(max_length=100)
is_deleted = models.BooleanField(default=False)
email = models.EmailField()
objects = models.Manager()
active = ActiveManager()
Теперь менеджер active возвращает только активные
профили пользователей:
from myapp.models import UserProfile
active_profiles = UserProfile.active.all()
print(active_profiles.count())
Результат выполнения кода:
"5"
Пример
Переопределим метод get_queryset для применения
аннотации к каждому запросу:
from django.db import models
from django.db.models import Count
class CommentedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().annotate(
comments_count=Count("comments")
)
class Article(models.Model):
title = models.CharField(max_length=200)
text = models.TextField()
objects = CommentedManager()
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE)
text = models.TextField()
Теперь каждый объект Article имеет дополнительное поле
comments_count:
from myapp.models import Article
article = Article.objects.first()
print(article.title)
print(article.comments_count)
Результат выполнения кода:
"Interesting article"
"3"