How To Add A Custom Managers In Django

Django Custom Managers

A Manager is used to query database operations which will be provided to Django models. Every model in Django application consists at least one Manager by default.

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.

 

Posted On 05 May 2017 By MicroPyramid


Need any Help in your Project?Let's Talk

Latest Comments
Related Articles
Sorl-thumbnail to generate thumbnails in django

Displaying and Customizing the images in django with sorl-thumbnail.

Continue Reading...
Introduction to API development using Django REST framework with Example

Introduction to API development with Django REST framework. You can build the API for any Django application. Pre-requisites are Django and OOPS(object oriented programming concepts) ...

Continue Reading...
Google plus API integration with django

Using GPlus integration, we can get the user verified email id, general information, friends in a less span of time, and user can also share ...

Continue Reading...
open source packages

Subscribe To our news letter

Subscribe and Stay Updated about our Webinars, news and articles on Django, Python, Machine Learning, Amazon Web Services, DevOps, Salesforce, ReactJS, AngularJS, React Native.
* We don't provide your email contact details to any third parties