.. _topics-db-managers: ======== Managers ======== .. currentmodule:: django.db.models .. class:: Manager() A ``Manager`` is the interface through which database query operations are provided to Django models. At least one ``Manager`` exists for every model in a Django application. The way ``Manager`` classes work is documented :ref:`topics-db-queries`; this document specifically touches on model options that customize ``Manager`` behavior. Manager names ============= By default, Django adds a ``Manager`` with the name ``objects`` to every Django model class. However, if you want to use ``objects`` as a field name, or if you want to use a name other than ``objects`` for the ``Manager``, you can rename it on a per-model basis. To rename the ``Manager`` for a given class, define a class attribute of type ``models.Manager()`` on that model. For example:: from django.db import models class Person(models.Model): #... people = models.Manager() Using this example model, ``Person.objects`` will generate an ``AttributeError`` exception, but ``Person.people.all()`` will provide a list of all ``Person`` objects. .. _custom-managers: Custom Managers =============== You can use a custom ``Manager`` in a particular model by extending the base ``Manager`` class and instantiating your custom ``Manager`` in your model. There are two reasons you might want to customize a ``Manager``: to add extra ``Manager`` methods, and/or to modify the initial ``QuerySet`` the ``Manager`` returns. Adding extra Manager methods ---------------------------- Adding extra ``Manager`` methods is the preferred way to add "table-level" functionality to your models. (For "row-level" functionality -- i.e., functions that act on a single instance of a model object -- use :ref:`Model methods `, not custom ``Manager`` methods.) A custom ``Manager`` method can return anything you want. It doesn't have to return a ``QuerySet``. For example, this custom ``Manager`` offers a method ``with_counts()``, which returns a list of all ``OpinionPoll`` objects, each with an extra ``num_responses`` attribute that is the result of an aggregate query:: class PollManager(models.Manager): def with_counts(self): from django.db import connection cursor = connection.cursor() cursor.execute(""" SELECT p.id, p.question, p.poll_date, COUNT(*) FROM polls_opinionpoll p, polls_response r WHERE p.id = r.poll_id GROUP BY 1, 2, 3 ORDER BY 3 DESC""") result_list = [] for row in cursor.fetchall(): p = self.model(id=row[0], question=row[1], poll_date=row[2]) p.num_responses = row[3] result_list.append(p) return result_list class OpinionPoll(models.Model): question = models.CharField(max_length=200) poll_date = models.DateField() objects = PollManager() class Response(models.Model): poll = models.ForeignKey(Poll) person_name = models.CharField(max_length=50) response = models.TextField() With this example, you'd use ``OpinionPoll.objects.with_counts()`` to return that list of ``OpinionPoll`` objects with ``num_responses`` attributes. Another thing to note about this example is that ``Manager`` methods can access ``self.model`` to get the model class to which they're attached. Modifying initial Manager QuerySets ----------------------------------- A ``Manager``'s base ``QuerySet`` returns all objects in the system. For example, using this model:: class Book(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=50) ...the statement ``Book.objects.all()`` will return all books in the database. You can override a ``Manager``\'s base ``QuerySet`` by overriding the ``Manager.get_query_set()`` method. ``get_query_set()`` should return a ``QuerySet`` with the properties you require. For example, the following model has *two* ``Manager``\s -- one that returns all objects, and one that returns only the books by Roald Dahl:: # First, define the Manager subclass. class DahlBookManager(models.Manager): def get_query_set(self): return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl') # Then hook it into the Book model explicitly. class Book(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=50) objects = models.Manager() # The default manager. dahl_objects = DahlBookManager() # The Dahl-specific manager. With this sample model, ``Book.objects.all()`` will return all books in the database, but ``Book.dahl_objects.all()`` will only return the ones written by Roald Dahl. Of course, because ``get_query_set()`` returns a ``QuerySet`` object, you can use ``filter()``, ``exclude()`` and all the other ``QuerySet`` methods on it. So these statements are all legal:: Book.dahl_objects.all() Book.dahl_objects.filter(title='Matilda') Book.dahl_objects.count() This example also pointed out another interesting technique: using multiple managers on the same model. You can attach as many ``Manager()`` instances to a model as you'd like. This is an easy way to define common "filters" for your models. For example:: class MaleManager(models.Manager): def get_query_set(self): return super(MaleManager, self).get_query_set().filter(sex='M') class FemaleManager(models.Manager): def get_query_set(self): return super(FemaleManager, self).get_query_set().filter(sex='F') class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female'))) people = models.Manager() men = MaleManager() women = FemaleManager() This example allows you to request ``Person.men.all()``, ``Person.women.all()``, and ``Person.people.all()``, yielding predictable results. If you use custom ``Manager`` objects, take note that the first ``Manager`` Django encounters (in the order in which they're defined in the model) has a special status. Django interprets this first ``Manager`` defined in a class as the "default" ``Manager``, and several parts of Django (though not the admin application) will use that ``Manager`` exclusively for that model. As a result, it's often a good idea to be careful in your choice of default manager, in order to avoid a situation where overriding of ``get_query_set()`` results in an inability to retrieve objects you'd like to work with. Using managers for related object access ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default, Django uses a "bare" (i.e. default) manager when accessing related objects (i.e. ``choice.poll``). If this default isn't appropriate for your default manager, you can force Django to use a custom manager for related object attributes by giving it a ``use_for_related_fields`` property:: class MyManager(models.Manager):: use_for_related_fields = True ... ...