How to use and create Custom Model Manager in Django for Beginners

In Django, Model Managers are classes that act as the interface between Django models and the database. A Model can have any number of managers and using these managers we can extend the functionality of the model.

Table of Contents

Introduction

An Introduction to Django Model Managers, we’ll start from the default model manager and then go through creating and customizing model managers.
In this post, we’ll take the example of a BlogModel and then create a custom model manager for it.

Create a Model

The first step is to create an app and name it blogs and make BlogModel in file models.py.

from datetime import datetime
from django.db import models
from django.contrib.auth.models import User

class BlogModel(models.Model): 

    BLOG_STATUS = (
        ('PUBLISH', 'Publish'),
        ('DRAFT', 'Draft'),
    )

    blog_id = models.AutoField(primary_key=True)
    user = models.ForeignKey( User, on_delete=models.CASCADE, related_name='blogs' )
    title = models.CharField(max_length=255)
    content = models.TextField(blank=True, null=True)
    status = models.CharField(max_length=7, choices=BLOG_STATUS)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta():
        db_table = 'blogs'
        verbose_name = 'Blog'
        verbose_name_plural = 'Blogs'

    def __str__(self):
        return self.title    

In BlogModel field user shares ForeignKey relationship with Django’s built-in AUTH_USER_MODEL.

Default Model Manager

If you haven’t specified any model manager to your models then Django implicitly adds a default model manager to your model. In this case model BlogModel does not have any specified model managers in such case objects will be assigned as model managers.

Anytime fetching, updating, or deleting rows are done through object model managers.
Some examples are shown below

from blogs.models import BlogModel

blog_list = BlogModel.objects.all()

blog_list = BlogModel.objects.filter(user=5)

If you want to use other model manager name insisted objects then you can also do that by assigning the default model manager to name with which
you would like to access the example shown below.

#in models.py
class BlogModel(models.Model): 
    ...
    ...
    ...
    custom_objects = models.Manager() 

#in python manage.py shell
>>> from datetime import datetime
>>> from django.db import models
>>> from django.contrib.auth.models import User
>>> from blogs.models import BlogModel
>>> blog_list = BlogModel.custom_objects.all()
>>> blog_list
, , ...(remaining elements truncated)...']>
Django list querysets using default model manager
Django list querysets using default model manager

And now if we try to retrieve data using objects then Django will throw AttributeError exception.

>>> blog_list = BlogModel.objects.all()
Traceback (most recent call last):
    File "/usr/lib/python3.5/code.py", line 91, in runcode
    exec(code, self.locals)
    File "", line 1, in 
AttributeError: type object 'BlogModel' has no attribute 'objects'
Django throws AttributeError when called to wrong model manager.
Django throws AttributeError when called to the wrong model manager.

Create Customer Model Manager

Custom models managers can be created by inheriting Django’s models.Manager which also is a default manager and provides much functionality related to querying querysets.

In our app blogs create a new file and name it managers.py and in that file import from django.db import models as shown below.

from django.db import models

class BlogModelManager(models.Manager):
    
    def get_queryset(self):
        queryset = super().get_queryset()
        return queryset

    def with_all_users(self):
        # returns blogs with inner joining auth user model
        queryset = self.get_queryset()
        queryset = queryset.select_related('user')
        return queryset

    def with_order_by_user_first_name(self, type="ASC"):
        queryset = self.with_all_users()
        field = 'user__first_name'
        if type=='DESC':
            field = '-user__first_name'
        queryset = queryset.order_by(field)
        return queryset

Now we have created our custom model manager its all it to BlogModel.

from blogs.managers import (BlogModelManager, )


class BlogModel(models.Model): 
    ...
    ...
    ...
    objects = BlogModelManager();

In BlogModelManager we have specified three methods the first get_queryset(self) method is the built-in method which returns the queryset.
with_all_users(self) method calls get_queryset() and also makes inner join with user which is Django’s default user model.
The queryset method select_related() creates an inner join and while calling this method the query will be like below.

SELECT `blogs`.`blog_id`, `blogs`.`user_id`, `blogs`.`title`, `blogs`.`content`, `blogs`.`status`, 
`blogs`.`created_at`, `blogs`.`updated_at`, `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`,
`auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, 
`auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined`
FROM 
`blogs` INNER JOIN `auth_user` 
ON (`blogs`.`user_id` = `auth_user`.`id`)

The method with_order_by_user_first_name(self, type="ASC") will order the queryset by field first_name of Django’s default auth user model.
This method will execute as the below query.

SELECT `blogs`.`blog_id`, `blogs`.`user_id`, `blogs`.`title`, `blogs`.`content`, `blogs`.`status`, 
`blogs`.`created_at`, `blogs`.`updated_at`, `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`,
`auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, 
`auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` 
FROM `blogs` INNER JOIN `auth_user` 
ON (`blogs`.`user_id` = `auth_user`.`id`) 
ORDER BY `auth_user`.`first_name` ASC

In python shell, you can call these methods shown below.

blogs = BlogModel.objects.with_all_users()
blogs_ordered_by_fname = BlogModel.objects.with_order_by_user_first_name(type="DESC")

Conclusion

We have come to the end of our post on How to use and create Custom Model Manager in Django for Beginners. If you like our content then please do share it and comment to clarify your doubts. We thank you from bottom of our heart.

Related Posts

Summary
Review Date
Reviewed Item
How to use and create Custom Model Manager in Django for Beginners
Author Rating
51star1star1star1star1star
Software Name
Django Framework
Software Name
Windows Os, Mac Os, Ubuntu Os
Software Category
Web Development