Menu Close

Django Model Manager

Django model manager

Hi Django Developers, I Hope you are doing well. In this article, I’m gonna explain to you all about the Django model manager with the help of the proper example so that you don’t have any confusion regarding the model manager in Django. This is one of the most confusing topics, especially for beginner programmers but after this Django model manager tutorial, you will be completely able to work with Django model manager.

Note:- If you don’t know what is Django model, Click here to learn all about Django models.

What is Django Model Manager?

Django model manager is the interface through which database query operations perform to the Django models.

In other words, Django model manager is an instance of the Manager class that allows us to interact with Django models through database query operations.

At least one model manager exists in every model in the Django application. A Django model can have more than one manager. Your model can have a default manager and add some additional managers that you define.

OR

Django model manager is one of the major tools in Django’ORM that is used by developers to interact with the database.

Django Model Manager Name

By default, The Manager class adds a manager to every model called objects but if you want to use objects as the field of the model or you want to use another model manager name instead of objects then you have to rename it as per model basis.
To rename the model manager in Django you have to make an instance of the Manager class within the Django model.

Django Default Model Manager

Without changing the model manager in Django. Django makes available objects as a default model manager to each Django model.
As you can see in the below Student model, we did not change the default model manager objects so you can perform all the database operations through the objects model manager.

Example:- Django Default Model Manager


class Student(models.Model):
    college = models.ForeignKey(College, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=30, db_column="student_first_name", verbose_name=" Student First Name")
    last_name = models.CharField(max_length=20, db_column="student_last_name", verbose_name=" Student Last Name")
    email = models.EmailField(verbose_name="Student's email")
    gender = models.CharField(max_length=5, verbose_name="Student choice", choices=choice)
    roll_no = models.CharField(max_length=10, verbose_name="Student roll number")
    course = models.CharField(max_length=10, verbose_name="Course name of the student")
    address = models.TextField(verbose_name="Student's address", max_length=150)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

For better understanding, you can prefer the below screenshot.

Changing Default Django Model Manager

To change the default Django model manager, you have to create an instance of the models.Manager() class inside a Django model. Manager class has written inside django.db.models module.
In the below Django model, as you can see I am changing the default model manager from objects to students.

Example:- Changing Default Model Manager in Django


from django.db import models

choice = [
    ('M', "Male"),
    ('F', "Female")
]

class Student(models.Model):
    college = models.ForeignKey(College, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=30, db_column="student_first_name", verbose_name=" Student First Name")
    last_name = models.CharField(max_length=20, db_column="student_last_name", verbose_name=" Student Last Name")
    email = models.EmailField(verbose_name="Student's email")
    gender = models.CharField(max_length=5, verbose_name="Student choice", choices=choice)
    roll_no = models.CharField(max_length=10, verbose_name="Student roll number")
    course = models.CharField(max_length=10, verbose_name="Course name of the student")
    address = models.TextField(verbose_name="Student's address", max_length=150)

    students = models.Manager()

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

Now you can see in the above example, that we have successfully changed the model manager so we can’t use Student.objects statement to interact with the database. When we will try to use Student.objects then it will generate an AttributeError exception.

For better understanding, you can see the below screenshot, because we have summarized all the above things within a single image.

Using Django Model Manager

To use the Django default model manager or custom model manager to perform database query operations, you have to follow the basic syntax shown below.

Syntax:-

django_model_name.model_manager_name.manager_method

Let’s understand the above syntax through a Django model. As you can see, we have a simple Django model Person and also changed the default manager to people, Now we are going to see how the above syntax fits with this Model.


from django.db import models

class Person(models.Model):
	first_name = models.CharField(max_length=30, db_column="person_first_name", verbose_name="Person First Name")
    last_name = models.CharField(max_length=20, db_column="person_last_name", verbose_name="Person Last Name")
    email = models.EmailField(verbose_name="Person's email")
	
    people = models.Manager()

Note:- The manager class is a class that comes with Django by default and it is defined inside django.db.models the module. But don’t worry Django allows us to extend the Manager class as well, which we described below.

Custom Django Model Manager

You can use a custom model manager in Django in a particular model by extending the Manager class and instantiating your custom manager in your model.

There are two reasons that might extend the Manager class: to add an extra manager method or change the initial QuerySet that returns by the manager.

Adding extra manager method

Here I’m going to add a custom manager method that is responsible for fetching all the students whose gender is Male from the Student model. To add an extra manager method we have to extend the models.Manager class and define the method inside that class that we want to create.

Adding extra Manager methods is the preferred way to implement a way to add table label functionality.

This custom Manager add get_male() method.

Example:- How to add an extra manager method in Django


from django.db import models

choice = [
    ('M', "Male"),
    ('F', "Female")
]

class CustomManager(models.Manager):
    def get_male(self):
        return self.filter(gender='M')


class Student(models.Model):
    college = models.ForeignKey(College, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=30, db_column="student_first_name", verbose_name=" Student First Name")
    last_name = models.CharField(max_length=20, db_column="student_last_name", verbose_name=" Student Last Name")
    email = models.EmailField(verbose_name="Student's email")
    gender = models.CharField(max_length=5, verbose_name="Student choice", choices=choice)
    roll_no = models.CharField(max_length=10, verbose_name="Student roll number")
    course = models.CharField(max_length=10, verbose_name="Course name of the student")
    address = models.TextField(verbose_name="Student's address", max_length=150)

    students = CustomManager()

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

So we have successfully added the custom model manager CustomManager along with the method get_male(), Now you can get all the male students by using the Student.students.get_male() statement.

Modify a manager’s initial QuerySet

Before going further let’s understand what exactly the initial QuerySet is, for using the BlogPost model, when you use BlogPost.objects.all() statement then it returns QuerySet ( BlogPost models instances ), and this QuerySet is called initial QuerySet.

A manager’s base query returns all the objects of the model by default but we can change it. For example, using this example.

The BlogPost.objects.all() will return all the instances or posts of the BlogPost class but you can change it by overriding the manager.get_qyeryset() method. get_queryset() method will return the QuerySet along with the properties you require.

Example:- Modify initial manager QuerySet


from django.db import models

choice = [
    ('Publish', "Publish"),
    ('Draft', "Draft")
]


class CustomManager(models.Manager):
    # change initial queryset
    def get_queryset(self):
        return super().get_queryset().filter(status='Publish')


class BlogPost(models.Model):
    post_title = models.CharField(max_length=100, db_column="post_title", verbose_name="Post Title")
    post_description = models.TextField(max_length=200, db_column="post_description", verbose_name="Post Description")
    post_body = models.TextField(max_length=2000, db_column="post_body", verbose_name="Post Body")
    status = models.CharField(max_length=10, verbose_name="Blog Post Status", choices=choice)

    objects = models.Manager()  # This is the default manager
    publish_post = CustomManager()  # Custom manager

    def __str__(self):
        return f"{self.post_title} - Status:- {self.status}"

In the above Django model, there are two managers: publish_post will return all the published posts from BlogPost objects and objects will return all the BlogPost’s instances.

Custom QuerySet Method

You have to remember one most important point here: BlogPost.objects.all() or all() method returns QuerySet which is the instance of QuerySet class.

QuerySet class written inside django.db.models package.

So far we have seen how to add an extra manager method and modify the initial manager’s QuerySet now I am going to add some extra QuerySet methods that will be directly accessible from the model manager in Django and also apply on QuerySet.

For using this example, I’m going to add the total of two methods: get_publish() for fetching only Published posts and get_draft() for fetching only Draft blog posts.

Example:- How to add custom QuerySet methods in Django

from django.db import models

choice = [
    ('Publish', "Publish"),
    ('Draft', "Draft")
]

class BlogPostQuerySet(models.QuerySet):
    def get_publish(self):
        return self.filter(status="Publish")

    def get_draft(self):
        return self.filter(status='Draft')

class CustomManager(models.Manager):

    def get_queryset(self):
        return BlogPostQuerySet(self.model, using=self._db)

    def get_publish(self):
        return self.get_queryset().get_publish()

    def get_draft(self):
        return self.get_queryset().get_draft()


class BlogPost(models.Model):
    post_title = models.CharField(max_length=100, db_column="post_title", verbose_name="Post Title")
    post_description = models.TextField(max_length=200, db_column="post_description", verbose_name="Post Description")
    post_body = models.TextField(max_length=2000, db_column="post_body", verbose_name="Post Body")
    status = models.CharField(max_length=10, verbose_name="Blog Post Status", choices=choice)

    posts = CustomManager()

    def __str__(self):
        return f"{self.post_title} - Status:- {self.status}"

With this example, you can call both get_publish() and get_draft() method directly from the Django model manager as well as QuerySet as you can see below screenshot.

Conclusion

So In this article, we have seen all about the Django model managers along with examples. If you are a Beginners Django developer or you don’t have knowledge of Django model manager, Then I will highly recommend, you should have knowledge of Django model manager because It is one of the most important concepts in the Django web framework and it is a tool that used by developers to interact with the database and perform database query operations.

Here I have covered what is a model manager in Django and also I have seen how to create a custom Django model manager, custom model manager methods, and how to create custom QuerySet methods that are directly accessible by the Django model manager.

If this article is helpful for you, please share and keep visiting for further Django tutorials.

Ref:- Click Here

Thanks for your valuable time... 🙏🙏

Previous Article
Next Article

Related Posts