A Model Manager is used when you don't just want to retrieve a single instance of a model with special criteria, but you want to fill an entire QuerySet with those special criteria. All instances of this model in the database are to be filtered using the special criteria.
There are several ways to create a Model Manager. You can create additional functions / methods for the Manager. Or you can create your own Model Manager and override the get_queryset()
method.
In our case, I have decided to override the get_queryset()
method in the custom Model Manager and now have two Manger available for filtering. We can use the Model Manager to filter all our Post instances by status "Published". So we are going to modify the initial QuerySet of our Model Manager.
# blog/models.py
from django.db import models
from django.urls import reverse
from django.utils import timezone
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status=Post.Status.PUBLISHED)
class Post(models.Model):
class Status(models.TextChoices):
DRAFT = "DF", "Draft"
PUBLISHED = "PB", "Published"
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique_for_date="publish")
author = models.ForeignKey(
"account.User", on_delete=models.CASCADE, related_name="blog_posts"
)
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=2, choices=Status, default=Status.DRAFT)
objects = models.Manager() # The default manager.
published = PublishedManager() # Our custom manager.
class Meta:
ordering = ["-publish"]
indexes = [
models.Index(fields=["publish"]),
]
def __str__(self):
return self.title
get_queryset()
: The objects you want to retrieve are determined by the get_queryset()
method.Now we have two managers. We can use them to retrieve, filter and manipulate our Post model instances. You can use Post.objects.all()
, this will give you a QuerySet with all the instances of the Post model. And if you use Post.published.all()
you will get all the instances of the Post model that have the status="Published"
.