Create a blog application with django, part 4: django querysets and managers

Now that you have a fully functional administration site to manage your blog's content, it's time to learn how to retrieve information from the database and interact with it. Django comes with a powerful database abstraction API that lets you create, retrieve, update, and delete objects easily. The Django Object-relational mapper (ORM) is compatible with MySQL, PostgreSQL, SQLite, and Oracle. Remember that you can define the database of your project in the DATABASES setting of your project's settings.py file. Django can work with multiple databases at a time, and you can program database routers to create custom routing schemes.

The Django object-relational mapping (ORM) is based on QuerySets. A QuerySet is a list of objects of a given model. QuerySets allow you to read the data from the database, filter it and order it. You can find more information about Django Querysets here .

Using the filter() method

To filter a QuerySet, you can use the filter() method of the manager. For example, we can retrieve all posts published in the year 2019 using the following QuerySet:

Post.objects.filter(publish__year=2019)

You can also filter by multiple fields. For example, we can retrieve all posts published in 2019 by the author with the username admin:

Post.objects.filter(publish__year=2019, author__username='admin')

Using order_by()

You can order results by different fields using the order_by() method of the manager. For example, you can retrieve all objects ordered by their title, as follows:

Post.objects.order_by('title')

Ascending order is implied. You can indicate descending order with a negative sign prefix, like this:

Post.objects.order_by('-title')

You can find more information about methods that return new QuerySets here .

Creating model managers

In a Django model, the Manager is the interface that interacts with the database, objects is the default manager of every model that retrieves all objects in the database. However, we can also define custom managers for our models. We will create a custom manager to retrieve all posts with the published status.

There are two ways to add managers to your models: you can add extra manager methods or modify initial manager QuerySets. The first method provides you with a QuerySet API such as Post.objects.my_manager(), and the latter provides you with Post.my_manager.all(). The manager will allow us to retrieve posts using Post.published.all().

Edit the blog/models.py file of your blog application to add the custom manager like this:

# blog/models.py

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User


class PublishedManager(models.Manager):
   def get_queryset(self):
       # Displays only published post
       return super().get_queryset().filter(status='published')  # ========= New lines

class Post(models.Model):
   STATUS_CHOICES = (
       ('draft', 'Draft'),
       ('published', 'Published'),
   )
   title = models.CharField(max_length=250)
   slug = models.SlugField(max_length=250,
                           unique_for_date='publish')
   author = models.ForeignKey(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=10,
                             choices=STATUS_CHOICES,
                             default='draft')

   objects = models.Manager() # The default manager. ============== New line
   published = PublishedManager() # The custom manager. =========== New line

   class Meta:
       ordering = ('-publish',)

   def __str__(self):
       return self.title

That's it for now. The next tutorial is to learn how to write Django views.


If you like my content, please consider buying me a coffee.
Thank you for your support!

Related posts