Метод get_queryset

Метод get_queryset используется в кастомных менеджерах для определения QuerySet, который будет возвращаться по умолчанию при вызове менеджера модели. Этот метод часто переопределяется для добавления фильтрации, сортировки или других модификаций запросов на уровне менеджера. Метод не принимает дополнительных аргументов и возвращает экземпляр QuerySet.

Синтаксис

pythonclass CustomManager(models.Manager):
  def get_queryset(self):
    return super().get_queryset().filter(condition)

Пример

Создадим кастомный менеджер, который по умолчанию возвращает только опубликованные статьи:

pythonfrom 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 будут возвращаться только опубликованные статьи:

pythonfrom myapp.models import Article

published_articles = Article.published.all()
print(published_articles)

Результат выполнения кода:

python[<Article: First article>, <Article: Second article>]

Пример

Переопределим метод get_queryset для добавления сортировки по умолчанию:

pythonfrom 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()

При запросе всех записей они автоматически сортируются по дате создания в обратном порядке:

pythonfrom myapp.models import Post

posts = Post.objects.all()
for post in posts:
  print(post.title)

Результат выполнения кода:

python"Newest post"
"Middle post"
"Oldest post"

Пример

Создадим менеджер, который исключает из выборки записи с определённым статусом:

pythonfrom 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 возвращает только активные профили пользователей:

pythonfrom myapp.models import UserProfile

active_profiles = UserProfile.active.all()
print(active_profiles.count())

Результат выполнения кода:

python"5"

Пример

Переопределим метод get_queryset для применения аннотации к каждому запросу:

pythonfrom 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:

pythonfrom myapp.models import Article

article = Article.objects.first()
print(article.title)
print(article.comments_count)

Результат выполнения кода:

python"Interesting article"
"3"

Смотрите также

  • класс Manager,
    который предоставляет интерфейс для работы с запросами к базе данных
  • атрибут objects,
    который является стандартным менеджером модели
  • метод filter,
    который применяет фильтрацию к QuerySet
  • метод exclude,
    который исключает записи из QuerySet