Django Quick Tips #1: Managers

February 12, 2007

This post is the first in a series of "Quick Tips" for Django, short bits of information not meant to be exhaustive but introductory. Django is such a massive framework that it's easy to miss a great feature. It's also easy to miss the point of functionality when it isn't accompanied with a useful example.

This Quick Tip is a brief explanation of Managers. From the Django docs:

A Manager is the interface through which database query operations are provided to Django models.

Django automatically assigns the default manager with the name objects, giving us read/write access to our new model.

MyModel.objects.all() # Using the Manager's built-in all() method

Here's a real world example of why it might be prudent to create a custom manager. Let's say we have a simple blog model that allows us to publish/unpublish our posts.

from django.db import models

class Post(models.Model):
        title = models.CharField(maxlength=100)
        text = models.TextField()
        published = models.BooleanField()

Now, when we want to show a published article we have to filter it by published.

Post.objects.filter(published=True)

Unfortunately, it can be easy to forget since you're going to be putting this in many places. Instead, we'll create a Manager to do the work for us. A Manager essentially helps us build a queryset, so creating a custom manager allows us to filter the queryset.

Here is our PublishedPostManager:

class PublishedPostManager(models.Manager):
  def get_query_set(self):
      return super(PublishedPostManager,
                  self).get_query_set().filter(published=True)

We put that above our Model and add it as published_objects.

from django.db import models

class Post(models.Model):
        title = models.CharField(maxlength=100)
        text = models.TextField()
        published = models.BooleanField()

        objects = models.Manager()
        published_objects = PublishedPostManager()

Note: We must add the objects default Manager if we want it back, otherwise Django will use published_objects as the default instead. That would make all unpublished posts disappear, including the admin panel!

Now, we can pass the published_objects as our queryset:

Post.published_objects.all() # Only returns posts where published == True
Post.objects.all()           # Returns all posts

If we change the criteria of what it means to be published, for example "date must be today or older", then we only have to modify the queryset in the Model. This certainly reduces code and the possibility for error and oversight.

Hopefully this example will give you a glimpse of what Managers can do for you. The Django docs are a good place for more information.


Comments

Clean and nice. Shows what django can do rather well I think.

Posted by Tony

Thanks, this is quite clear and strait forward.

Posted by Noah

quick and informative, thx!

Posted by costi

Thanks, just what I needed

Posted by a

Awesome! Saved me hours of searching.

Thanks!

Posted by James

Managers were fuzzy to me until i read this post. Thanks.

Posted by shannon

Add your comment

No HTML; Only URLs and line breaks are converted.