Django Tips: Custom Model Managers

Every Django model comes with its own model manager. The manager is how you interact with your Django models to do database queries. Whenever you call your model with Model.objects.all(), for example, you're using the built-in manager for your model.

You might have a query that you run in more than one place in your codebase. If you run a pizza parlor, for example, you might want to get the "special" pizzas:

return Pizza.objects.filter(special=True)

But at some point your models might change. Maybe you add an active field to the model so you can store seasonal pizzas and mark them as "inactive" when it's not the right season for them anymore. Then your query needs to change:

return Pizza.objects.filter(special=True, active=True)

You have to make this change every place you make this query for pizza specials, which might be in several places.

Enter custom model managers! You can create your own custom model managers to deal with queries that occur frequently in your code. Then you can change the query in one place when your conditions change. You do this by overriding the built-in model manager and adding methods to it.

from django.db import models 

class PizzaManager(models.Manager):
    def specials(self):
        return self.get_queryset().filter(special=True, active=True)

Then tell your Django model to use this new, custom manager instead of the default manager.

from django.db import models

from .managers import PizzaManager 

class Pizza(models.Model):
    objects = PizzaManager()

Now you can call Pizza.objects.specials() to get your specials!

This article uses Django 2.1. Thanks Jeff for proofreading this article.