DEV Community

MeetParikh01 for BoTreeTechnologies

Posted on • Originally published at botreetechnologies.com

Definitive Guide for Adding Custom Model Managers in Django

Django managers

What is a manager?

A manager is an interface through which database query operations are provided to django models. It is some kind of 'gate' between application and database

Hence, there exists at least one manager for every model in a django application.

In this case, django adds the default manager with the name objects is used.

We can even rename the manager's name on a pre model basis . So let us consider a Student Model.

Here, we can access Student model queries like Student.student.all() where student is the manager's name.

Benefits of using managers in your code:

  • Clean code.
  • Efficient code.
  • Maintainable code.
  • Writing common query code for the model which are reusable. (DRY rule i.e. Don’t repeat yourself)

How to write custom managers?

A custom Manager is created by extending a base Manager class in a particular model and by instantiating the created custom manager within the model.

We have created a custom manager by name StudentManager and thus, our managers looks like -

Thus, to access a Student Model with different queries defined in the StudentManager, it can be done like this -

Though in the given examples we have returned the queryset, one can return anything like a list, dictionary, attribute value etc.

Modifying a manager initial QuerySet

A Manager’s base QuerySet returns all objects in the system. For example, in our Student Model we get all the objects using Student.student.all() but if we want to modify the initial queryset then we need to override a Manager’s base QuerySet by overriding the manager.get_queryset() method. get_queryset() should return a QuerySet with the properties we require.

So here we have created two managers for our Student Model by name MaleManager and FemaleManager and instantiated them by name male and female, so our MaleManager and FemaleManager looks as and their access like.

ProjectStatusSerializerCalling custom QuerySet method from the manager

Most of the methods from the standard QuerySet are directly accessible from the manager but if we want to add methods that need to be accessible as attributes then we need to define Custom Queryset.

We need to do this because the methods defined in the manager are not chainable.

For example, in our StudentManager we have a method by name get_males() if we try to chain it with get_students_age_less_or_equal() then it will throw error like this -

So, to make it work, we will define our own QuerySets Method and using that method in a seperate manager named as StudentModifyManager

Now as in our models we have instantiate our StudentModifyManager as modify named object, so we can use the chainable methods as -

Creating a manager with QuerySet Methods.

While calling StudentQuerySet Methods, we need to duplicate its methods in our StudentModifyManager. If we don’t want to duplicate those methods then we can create a manage with queryset methods.

In our Student Model we have created a manager with object query as
query
= StudentQuerySet.as_manager()

Now, we can use that manager as Student.query.male().get_sem3_students() and can get output according to it.

Thus, here the StudentQuerySet.as_manager() is virtually identical to the StudentModifyManager .

from_queryset method: classmethod from_queryset(queryset_class)

If we want the custom Manager and the custom QuerySet for the advanced usage then it can be done by Manager.from_queryset() which returns the subclass of the base class with a copy of the custom Queryset methods.

So in our Student model, we have done it by creating a custom object in the model as

custom = StudentModifyManager.from_queryset(StudentQuerySet)() where the StudentModifyManager is our custom Manager and the StudentQuerySet is our custom QuerySet

Now looking at the output in our shell -

Conclusion

Django managers ensure that you write code which is easily maintained and adhere to the DRY principle. They allow keeping queries at a centralized location so that all the queries come from a single location instead of flying in from everywhere.

Click here for more details…

Top comments (1)

Collapse
 
userzero profile image
User Zero • Edited

Glaring mistakes in this article, may mislead noobs.

Under section "How to write custom managers?", you have:

class StudentManager(models.Manager):
  # ...
  def get_male_students_age_less_or_equal(self,age):
      return self.filter(gender='male').get_students_age_less_or_equal(age)
  # ...
Enter fullscreen mode Exit fullscreen mode

Above will not work. In self.filter, self is Manager object, and Manager.filter returns a QuerySet object, and that does not have method get_students_age_less_or_equal().