How To Add A Custom Managers In Django

Reading Time : ~ .

Django Custom Managers

A Manager is the interface through which database query operations are provided to Django models. At least one Manager exists for every model in a Django application.

Regarding the Manager names:
By default, Django adds a Manager with the name "objects" to every Django model class. However, if you want to use "objects" as a field name (or) if you want to use a name instead of "objects" for the Manager, you can rename it on a per-model basis. To rename the Manager for a given class, define a class attribute of type models.Manager() on that model.
For example:

from django.db import models

class Employee(models.Model):
      gender_choices = (
           ("M", "Male"),
           ("F", "Female")
      )
      roles_choices = (
           ("J", "Junior"),
           ("S", "Senior"),
      )
      first_name = models.CharField(max_length=200)
      last_name = models.CharField(max_length=200)
      email = models.CharField(max_length=250)
      gender = models.CharField(max_length=1, choices=gender_choices)
      role = models.CharField(max_length=120, choices=roles_choices, default="J")
      active = models.BooleanField(default=True)

      # custom manager replaces objects manger
      all_employees = models.Manager()

      def __str__(self):
            return str(self.first_name) + str(self.last_name)

Using the above example model, Employee.objects will throw you an AttributeError exception, but Employee.all_employees.all() will provide a list of all Employee objects.

Now, here we go for the Custom Managers:

You can use a custom Manager in a particular model by extending the base Manager class and instantiating your custom Manager in your model.
There are two reasons you might want to customize a Manager: to add extra Manager methods, and/or to modify the initial QuerySet the Manager returns.

Note: Manager methods can access self.model to get the model class to which they’re attached.

Here I'm gonna explain Modifying a manager’s initial QuerySet for now:

A Manager’s base QuerySet returns all objects in the system. For example, from the above example using Employee model (except the Custom Manager name):

the statement Employee.objects.all() will return all employees in the database.
You can override a Manager’s base QuerySet by overriding the Manager.get_queryset() method. get_queryset() should return a QuerySet with the properties you require.

For example, the following model has two Managers – one that returns all objects, and one that returns only the active employees:

    # First, define the Manager subclass.
    class EmployeeManager(models.Manager):
        def get_queryset(self):
            return super(EmployeeManager, self).get_queryset().filter(active=True)

    # Then hook it into the Employee model explicitly.
    class Employee(models.Model):
        .....
        active = models.BooleanField(default=True)

        objects = models.Manager() # The default manager.
        active_objects = EmployeeManager() # The EmployeeManager manager.

With this sample model, Employee.objects.all() will return all employees in the database, but Employee.active_objects.all() will only return the ones who are in active state.

Of course, because get_queryset() returns a QuerySet object, you can use filter(), exclude() and all the other QuerySet methods on it. So these statements are all legal:

    Employee.active_objects.all()
    Employee.active_objects.filter(email='employee@gmail.com')
    Employee.active_objects.count()

This example also pointed out another interesting technique: using multiple managers on the same model. You can attach as many Manager() instances to a model as you’d like. This is an easy way to define common “filters” for your models.

For example:

class SeniorManager(models.Manager):
    def get_queryset(self):
        return super(SeniorManager, self).get_queryset().filter(role='S')

class JuniorManager(models.Manager):
    def get_queryset(self):
        return super(JuniorManager, self).get_queryset().filter(role='J')

class Employee(models.Model):
    ...
    roles_choices = (
        ("J", "Junior"),
        ("S", "Senior"),
    )
    ....
    role = models.CharField(max_length=1, choices=role_choices)

    all_employees = models.Manager()
    seniors = SeniorManager()
    juniors = JuniorManager()

This example allows you to request Employee.all_employees.all(), Employee.seniors.all() and Employee.juniors.all() yielding predictable results.

 

Calling custom QuerySet methods from the manager:

While most methods from the standard QuerySet are accessible directly from the Manager, this is only the case for the extra methods defined on a custom QuerySet if you also implement them on the Manager:

class EmployeeQuerySet(models.QuerySet):
    def juniors(self):
        return self.filter(role='J')

    def seniors(self):
        return self.filter(role='S')

class EmployeeManager(models.Manager):
    def get_queryset(self):
        return EmployeeQuerySet(self.model, using=self._db)

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

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

class Employee(models.Model):
    ...
    roles_choices = (
        ("J", "Junior"),
        ("S", "Senior"),
    )
    ....
    role = models.CharField(max_length=1, choices=role_choices)

    all_employees = EmployeeManager()

This example allows you to call both juniors() and seniors() directly from the manager Employee.all_employees.

 

    By Posted On
SENIOR DEVELOPER at MICROPYRAMID

Need any Help in your Project?Let's Talk

Latest Comments
Related Articles
How to customize the admin actions in list pages of Django admin? Chaitanya Kattineni

Django by default provides automatic admin interface, that reads metadata from your models to provide a beautiful model interface where trusted users can manage content ...

Continue Reading...
Custom Password Less Authentication in Django Nikhila Mergu

Authentication backends allow the ability to change what method checks your users credentials.

For web services, ie Facebook authentication, you don't have access to user ...

Continue Reading...
Django permissions and Groups Ashwin Kumar

Django comes with a simple permissions system. It provides a way to assign permissions to specific users and groups of users. We can have permissions ...

Continue Reading...

Subscribe To our news letter

Subscribe to our news letter to receive latest blog posts into your inbox. Please fill your email address in the below form.
*We don't provide your email contact details to any third parties