The importance of Django Model Managers

Apr 12, 2017
the_importance_of_django_model_managers main.png
5 min read

What is a Model Manager?


For every model in Django, there is an associated manager which is an interface for interacting with the database. To access the manager of a model, you simply need to use the objects property on the model e.g. FootballTeam.objects, however, this property is customisable.


If you wanted the manager property to be named teams, you would simply declare an attribute named teams of type Manager within the model.


                                                                   Screen Shot 2017-04-10 at 11.47.52 AM.png



from django.db import models

    teams = models.Manager()


There is a very big use case for creating a custom model manager for each model in your django application and this is a beneficial habit to get into for both yourself and other developers that have to work with the data models. This use case is maintenance.


Why are Model Managers so important?


As mobile app developers, we should be writing clean, efficient, maintainable code and follow the DRY (Don’t Repeat Yourself) software architecture principle. The django model managers play a good part in ensuring you tick all of these boxes; being more vital for maintenance and adhering to the DRY principle.


The reason it ticks these boxes is that it keeps the querying in your django application in a centralised place; queries that your application perform come from one place instead of being wrote on the fly in each View that requires the query.


                     Screen Shot 2017-04-10 at 11.48.56 AM.png


Consider the following example:    


FootballTeam Model

from django.db import models.DateField

import datetime

class FootballTeam(models.Model):
PREMIER_LEAGUE = 0 CHAMPIONSHIP = 1 LEAGUE_ONE = 2 LEAGUE = ( (PREMIER_LEAGUE, "Premier League"), (CHAMPIONSHIP, "Championship"), (LEAGUE_ONE, "League One"), ) name = models.CharField("Name", max_length=255, default="") nickname = models.CharField("Nickname", max_length=255, default="") league = models.IntegerField("League", choices=LEAGUE, default=0) founded = models.DateField("Founded", default =


Note: League would normally be a separate model here, however, for the purpose of this example, using a ChoiceField will suffice.


                     Screen Shot 2017-04-10 at 11.49.22 AM.png                             


Querying the FootballTeam Model  


API View:

from rest_framework.generics import ListAPIView

from .models import FootballTeam

class TopFootballTeamList(ListAPIView):
    def get_queryset(self):


Django View:

from django.views import generic

from .models import FootballTeam

class TopFootballTeamListView(generic.ListView):
    template_name = 'football/teams.html'
    model = FootballTeam

    def get_queryset(self):


The issue with the code above is there are two separate views which require the same functionality and therefore perform identical queries in the get_queryset method. This goes against the DRY principle and also causes extra development work when requiring to maintain these views.


If a requirement was to change and the “top football teams” were classed as Premier League and Championship teams rather than just Premier League teams, there are two views that have to be maintained regarding this query which leads to modifications having to be made in both respective views. The get_queryset method in both of these would have to be changed to the following:

from django.db.models import Q

    # View

    def get_queryset(self):
    FootballTeam.objects.filter(Q(league=FootballTeam.PREMIER_LEAGUE) |


This may seem like a very small problem having to alter the query in two places, however, this is a very simplified example. In large systems where there will be more views and more complex queries, this type of maintenance takes up development and testing time, makes debugging harder, goes against the DRY principle and due to a query potentially being missed, can lead to bugs.


Screen Shot 2017-04-10 at 11.49.35 AM.png


How can this problem be solved?


To solve this issue, we can make use of model managers to create a centralised area for retrieving the top football teams using the FootballTeam model. This is achieved by the following:

from django.db import models
from django.db.models import Q
import datetime

class FootballTeamManager(models.Manager):

    def top_teams(self, **kwargs):
        return self.filter(Q(league=FootballTeam.PREMIER_LEAGUE))


    LEAGUE_ONE = 2

    LEAGUE = (
        (PREMIER_LEAGUE, "Premier League"),
        (CHAMPIONSHIP, "Championship"),
        (LEAGUE_ONE, "League One"),

    name = models.CharField("Name", max_length=255, default="")
    nickname = models.CharField("Nickname", max_length=255, default="")
    league = models.IntegerField("League", choices=LEAGUE, default=0)
    founded = models.DateField("Founded",

    objects = FootballTeamManager()


In the code snippet above, a model manager has been created named FootballTeamManager. This manager will be the sole place for implementing queries regarding the FootballTeam model, and by following this, we have created our centralised place for queries regarding this model. This follows the DRY principle and also ensures we have a central place for all developers on the project to go to when they need to modify a query; this is maintainable code.


To associate the FootballTeamManager with the FootballTeam model, replace the default model manager with our custom manager by adding the following code to the FootballTeam model objects = FootballTeamManager().


Screen Shot 2017-04-10 at 11.49.55 AM.png



To integrate the new manager methods into our views, we simply have to modify the

get_queryset methods to use the following:

def get_queryset(self):
    return FootballTeam.objects.top_teams()


Now, when the requirement to change the definition of top football teams to be football teams both in the Premier League and the Championship, we only have to modify the top_teams method of the model manager, rather than the two separate views.

def top_teams(self, **kwargs):
    return self.filter(Q(league=FootballTeam.PREMIER_LEAGUE) |


Once this type of development is enforced into a django project, it means that any developer can come onto that project and have confidence that they can change the query in one place and do not have to have knowledge of all views in the application that use the query.




Use model managers! Once in the habit of writing and using model managers, you will find development time speeds up, you have a cleaner and maintainable codebase, less occurrences of bugs regarding queries and future developers on the project will be very appreciative of your work; even more so in bigger projects.



Did you know that there is an easier way to manage two sub views using custom StackView?



Learn more about Custom StackView


Share this article
Stephen Jefferson

Author Stephen Jefferson

Stephen is an iOS and Python/Django developer with 4 years of experience and graduated from Teesside University with a first class honours in Computer Science. He is passionate about software architecture, problem solving and Middlesbrough FC.

View more posts by this author


Challenges and opportunities in ARToolKit development.

The explosive rise of augmented reality presents a number of opportunities and challenges for developers. Learn more about the technicalities of AR and AR applications, as well as:

•  AR development software such as ARKit, ARCore, Daqri-ARToolkit and more.
•  The industries AR applications will transform.
•  Considerations in building an AR Toolkit.
•  The future of AR development.
Get your free whitepaper here