Django Custom Managers and Querysets Defining a basic manager using Querysets and `as_manager` method


Django manger is an interface through which the django model queries the database. The objects field used in most django queries is actually the default manager created for us by django (this is only created if we don't define custom managers).

Why would we define a custom manager/queryset?

To avoid writing common queries all over our codebase and instead referring them using an easier to remember abstraction. Example: Decide for yourself which version is more readable :

  • Only get all the active users : User.objects.filter(is_active=True) vs
  • Get all active dermatologists on our plaform : User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology') vs User.manager.doctors.with_specialization('Dermatology')

Another benefit is that if tomorrow we decide all psychologists are also dermatologists, we can easily modify the query in our Manager and be done with it.

Below is an example of creating a custom Manager defined by creating a QuerySet and using the as_manager method.

from django.db.models.query import QuerySet

class ProfileQuerySet(QuerySet):
    def doctors(self):
        return self.filter(user_type="Doctor", user__is_active=True)

    def with_specializations(self, specialization):
        return self.filter(specializations=specialization)

    def users(self):
        return self.filter(user_type="Customer", user__is_active=True)

ProfileManager = ProfileQuerySet.as_manager

We will add it to our model as below:

class Profile(models.Model):
    manager = ProfileManager()

NOTE : Once we've defined a manager on our model, objects won't be defined for the model anymore.