Django Custom Model Manager

In this article we are going to discuss Django Custom Model Manager & Django Default Model Manager. So, What is a manager?

A Manager is a bridge through which database queries talk with Django models. In other words, it is actually an interface which interacts with application and database. There is at least one Manager that exists for every model in a Django application named objects. It is the default manager of every model that retrieves data from the database.

In this article we will discuss about creating Custom Model Managers & why should we use them.

Benefits of using Managers

Writing clean, efficient, maintainable code and following the DRY (Don’t Repeat Yourself) software architecture principle is industry demands. The django model managers keeps the querying in a centralized place in our django application. We can call those queries where we need them instead of writing them in each View. So, the benefits of using Django Managers are:             

  1. Clean code.
  2. Efficient code.
  3. Maintainable code.
  4. Writing common query code for the model which are reusable.
  5. Following DRY (Don’t Repeat Yourself) principle.

Firstly, we will create a model

class Person(models.Model):
      GENDER = (
        ('M', 'Male'),
        ('F', 'Female'),
    )

    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    email = models.EmailField(unique = True,null=True)
    gender = models.CharField(max_length=1, choices= GENDER,default='N/A')

    #will add our manager here


    class Meta:
        verbose_name_plural = 'All Persons'

    @property
    def full_name(self):
        return f'{self.first_name} {self.last_name}'

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

After running migrations let’s create some objects in the admin panel.

Objects of Django Model
Objects of Person model

Here, we have 6 person objects. The query operations will be like these…

>>> from first_app.models import Person
>>>
>>> Person.objects.all()
<QuerySet [<Person: Inayra Mutahharah>, <Person: Zaira Anaya>, <Person: Zahra Ibnat>, <Person: Jon Doe>, <Person: Yeasir Arafat>, <Person: Arafat Yeasir>]>
>>>
>>> Person.objects.filter(gender = 'F')
<QuerySet [<Person: Inayra Mutahharah>, <Person: Zaira Anaya>, <Person: Zahra Ibnat>]>
>>>
>>> Person.objects.filter(gender = 'M').count()
3

Here, ‘objects’ is the name of our default manager which is capable of doing all basic QuerySets, then why would we need a custom model manager? If need these queries in different views we will have to write these long lines of codes everywhere & if we want to change some thing we will have to change everywhere. This tough and monotonous task can be simplified using Django Mangers. Let’s create custom managers for doing these…

Custom Model Managers

We will inherit the properties of models.Manager.

class PersonManager(models.Manager):
    def male_persons(self):
        return self.filter(gender='M')
      
    def female_persons(self):
        return self.filter(gender='F')

    def total_persons(self):
        return self.all().count()

Now we will add this manger as our Person model’s manager. To do this we will have to add this line of code in our Person model.

#will add our manager here
objects = PersonManager()

We are ready to query with our manager.

>>> from first_app.models import Person
>>> males = Person.objects.male_persons()
>>> males
<QuerySet [<Person: Jon Doe>, <Person: Yeasir Arafat>, <Person: Arafat Yeasir>]>
>>> females = Person.objects.female_persons()
>>> females
<QuerySet [<Person: Inayra Mutahharah>, <Person: Zaira Anaya>, <Person: Zahra Ibnat>]>

We can change the default manger name with whatever we want. Let’s name it ‘persons’.

#will add our manager here
persons = PersonManager()
>>> from first_app.models import Person
>>> Person.persons.all()
<QuerySet [<Person: Inayra Mutahharah>, <Person: Zaira Anaya>, <Person: Zahra Ibnat>, <Person: Jon Doe>, <Person: Yeasir Arafat>, <Person: Arafat Yeasir>]>
>>>
>>> Person.persons.all().count()
6
+ posts

Author | Python-Django Developer

+ posts

Full-stack Developer (Python | Django | React | React-Native | Angular | Vue)