123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 |
- ========
- 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 in :doc:`/topics/db/queries`;
- this document specifically touches on model options that customize ``Manager``
- behavior.
- .. _manager-names:
- 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
- <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::
- from django.db import models
- 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 p.id, p.question, p.poll_date
- ORDER BY p.poll_date 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(OpinionPoll)
- 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::
- from django.db import models
- 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_queryset()`` method. ``get_queryset()`` 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_queryset(self):
- return super(DahlBookManager, self).get_queryset().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_queryset()`` 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_queryset(self):
- return super(MaleManager, self).get_queryset().filter(sex='M')
- class FemaleManager(models.Manager):
- def get_queryset(self):
- return super(FemaleManager, self).get_queryset().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 the first ``Manager`` defined in a class as
- the "default" ``Manager``, and several parts of Django
- (including :djadmin:`dumpdata`) will use that ``Manager``
- exclusively for that model. As a result, it's a good idea to be careful in
- your choice of default manager in order to avoid a situation where overriding
- ``get_queryset()`` results in an inability to retrieve objects you'd like to
- work with.
- .. versionchanged:: 1.6
- The ``get_queryset`` method was previously named ``get_query_set``.
- .. _managers-for-related-objects:
- Using managers for related object access
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- By default, Django uses an instance of a "plain" manager class when accessing
- related objects (i.e. ``choice.poll``), not the default manager on the related
- object. This is because Django needs to be able to retrieve the related
- object, even if it would otherwise be filtered out (and hence be inaccessible)
- by the default manager.
- If the normal plain manager class (:class:`django.db.models.Manager`) is not
- appropriate for your circumstances, you can force Django to use the same class
- as the default manager for your model by setting the ``use_for_related_fields``
- attribute on the manager class. This is documented fully below_.
- .. _below: manager-types_
- .. _calling-custom-queryset-methods-from-manager:
- Calling custom ``QuerySet`` methods from the ``Manager``
- --------------------------------------------------------
- While most methods from the standard ``QuerySet`` are accessible directly from
- the ``Manager``, this is only the case for the extra methods defined on a
- custom ``QuerySet`` if you also implement them on the ``Manager``::
- class PersonQuerySet(models.QuerySet):
- def male(self):
- return self.filter(sex='M')
- def female(self):
- return self.filter(sex='F')
- class PersonManager(models.Manager):
- def get_queryset(self):
- return PersonQuerySet()
- def male(self):
- return self.get_queryset().male()
- def female(self):
- return self.get_queryset().female()
- 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 = PersonManager()
- This example allows you to call both ``male()`` and ``female()`` directly from
- the manager ``Person.people``.
- .. _create-manager-with-queryset-methods:
- Creating ``Manager`` with ``QuerySet`` methods
- ----------------------------------------------
- .. versionadded:: 1.7
- In lieu of the above approach which requires duplicating methods on both the
- ``QuerySet`` and the ``Manager``, :meth:`QuerySet.as_manager()
- <django.db.models.query.QuerySet.as_manager>` can be used to create an instance
- of ``Manager`` with a copy of a custom ``QuerySet``'s methods::
- class Person(models.Model):
- ...
- people = PersonQuerySet.as_manager()
- The ``Manager`` instance created by :meth:`QuerySet.as_manager()
- <django.db.models.query.QuerySet.as_manager>` will be virtually
- identical to the ``PersonManager`` from the previous example.
- Not every ``QuerySet`` method makes sense at the ``Manager`` level; for
- instance we intentionally prevent the :meth:`QuerySet.delete()
- <django.db.models.query.QuerySet.delete>` method from being copied onto
- the ``Manager`` class.
- Methods are copied according to the following rules:
- - Public methods are copied by default.
- - Private methods (starting with an underscore) are not copied by default.
- - Methods with a `queryset_only` attribute set to `False` are always copied.
- - Methods with a `queryset_only` attribute set to `True` are never copied.
- For example::
- class CustomQuerySet(models.QuerySet):
- # Available on both Manager and QuerySet.
- def public_method(self):
- return
- # Available only on QuerySet.
- def _private_method(self):
- return
- # Available only on QuerySet.
- def opted_out_public_method(self):
- return
- opted_out_public_method.queryset_only = True
- # Available on both Manager and QuerySet.
- def _opted_in_private_method(self):
- return
- _opted_in_private_method.queryset_only = False
- from_queryset
- ~~~~~~~~~~~~~
- .. classmethod:: from_queryset(queryset_class)
- For advance usage you might want both a custom ``Manager`` and a custom
- ``QuerySet``. You can do that by calling ``Manager.from_queryset()`` which
- returns a *subclass* of your base ``Manager`` with a copy of the custom
- ``QuerySet`` methods::
- class BaseManager(models.Manager):
- def __init__(self, *args, **kwargs):
- ...
- def manager_only_method(self):
- return
- class CustomQuerySet(models.QuerySet):
- def manager_and_queryset_method(self):
- return
- class MyModel(models.Model):
- objects = BaseManager.from_queryset(CustomQueryset)(*args, **kwargs)
- You may also store the generated class into a variable::
- CustomManager = BaseManager.from_queryset(CustomQueryset)
- class MyModel(models.Model):
- objects = CustomManager(*args, **kwargs)
- .. _custom-managers-and-inheritance:
- Custom managers and model inheritance
- -------------------------------------
- Class inheritance and model managers aren't quite a perfect match for each
- other. Managers are often specific to the classes they are defined on and
- inheriting them in subclasses isn't necessarily a good idea. Also, because the
- first manager declared is the *default manager*, it is important to allow that
- to be controlled. So here's how Django handles custom managers and
- :ref:`model inheritance <model-inheritance>`:
- 1. Managers defined on non-abstract base classes are *not* inherited by
- child classes. If you want to reuse a manager from a non-abstract base,
- redeclare it explicitly on the child class. These sorts of managers are
- likely to be fairly specific to the class they are defined on, so
- inheriting them can often lead to unexpected results (particularly as
- far as the default manager goes). Therefore, they aren't passed onto
- child classes.
- 2. Managers from abstract base classes are always inherited by the child
- class, using Python's normal name resolution order (names on the child
- class override all others; then come names on the first parent class,
- and so on). Abstract base classes are designed to capture information
- and behavior that is common to their child classes. Defining common
- managers is an appropriate part of this common information.
- 3. The default manager on a class is either the first manager declared on
- the class, if that exists, or the default manager of the first abstract
- base class in the parent hierarchy, if that exists. If no default
- manager is explicitly declared, Django's normal default manager is
- used.
- These rules provide the necessary flexibility if you want to install a
- collection of custom managers on a group of models, via an abstract base
- class, but still customize the default manager. For example, suppose you have
- this base class::
- class AbstractBase(models.Model):
- # ...
- objects = CustomManager()
- class Meta:
- abstract = True
- If you use this directly in a subclass, ``objects`` will be the default
- manager if you declare no managers in the base class::
- class ChildA(AbstractBase):
- # ...
- # This class has CustomManager as the default manager.
- pass
- If you want to inherit from ``AbstractBase``, but provide a different default
- manager, you can provide the default manager on the child class::
- class ChildB(AbstractBase):
- # ...
- # An explicit default manager.
- default_manager = OtherManager()
- Here, ``default_manager`` is the default. The ``objects`` manager is
- still available, since it's inherited. It just isn't used as the default.
- Finally for this example, suppose you want to add extra managers to the child
- class, but still use the default from ``AbstractBase``. You can't add the new
- manager directly in the child class, as that would override the default and you would
- have to also explicitly include all the managers from the abstract base class.
- The solution is to put the extra managers in another base class and introduce
- it into the inheritance hierarchy *after* the defaults::
- class ExtraManager(models.Model):
- extra_manager = OtherManager()
- class Meta:
- abstract = True
- class ChildC(AbstractBase, ExtraManager):
- # ...
- # Default manager is CustomManager, but OtherManager is
- # also available via the "extra_manager" attribute.
- pass
- Note that while you can *define* a custom manager on the abstract model, you
- can't *invoke* any methods using the abstract model. That is::
- ClassA.objects.do_something()
- is legal, but::
- AbstractBase.objects.do_something()
- will raise an exception. This is because managers are intended to encapsulate
- logic for managing collections of objects. Since you can't have a collection of
- abstract objects, it doesn't make sense to be managing them. If you have
- functionality that applies to the abstract model, you should put that functionality
- in a ``staticmethod`` or ``classmethod`` on the abstract model.
- Implementation concerns
- -----------------------
- Whatever features you add to your custom ``Manager``, it must be
- possible to make a shallow copy of a ``Manager`` instance; i.e., the
- following code must work::
- >>> import copy
- >>> manager = MyManager()
- >>> my_copy = copy.copy(manager)
- Django makes shallow copies of manager objects during certain queries;
- if your Manager cannot be copied, those queries will fail.
- This won't be an issue for most custom managers. If you are just
- adding simple methods to your ``Manager``, it is unlikely that you
- will inadvertently make instances of your ``Manager`` uncopyable.
- However, if you're overriding ``__getattr__`` or some other private
- method of your ``Manager`` object that controls object state, you
- should ensure that you don't affect the ability of your ``Manager`` to
- be copied.
- .. _manager-types:
- Controlling automatic Manager types
- ===================================
- This document has already mentioned a couple of places where Django creates a
- manager class for you: `default managers`_ and the "plain" manager used to
- `access related objects`_. There are other places in the implementation of
- Django where temporary plain managers are needed. Those automatically created
- managers will normally be instances of the :class:`django.db.models.Manager`
- class.
- .. _default managers: manager-names_
- .. _access related objects: managers-for-related-objects_
- Throughout this section, we will use the term "automatic manager" to mean a
- manager that Django creates for you -- either as a default manager on a model
- with no managers, or to use temporarily when accessing related objects.
- Sometimes this default class won't be the right choice. One example is in the
- :mod:`django.contrib.gis` application that ships with Django itself. All ``gis``
- models must use a special manager class (:class:`~django.contrib.gis.db.models.GeoManager`)
- because they need a special queryset (:class:`~django.contrib.gis.db.models.GeoQuerySet`)
- to be used for interacting with the database. It turns out that models which require
- a special manager like this need to use the same manager class wherever an automatic
- manager is created.
- Django provides a way for custom manager developers to say that their manager
- class should be used for automatic managers whenever it is the default manager
- on a model. This is done by setting the ``use_for_related_fields`` attribute on
- the manager class::
- class MyManager(models.Manager):
- use_for_related_fields = True
- # ...
- If this attribute is set on the *default* manager for a model (only the
- default manager is considered in these situations), Django will use that class
- whenever it needs to automatically create a manager for the class. Otherwise,
- it will use :class:`django.db.models.Manager`.
- .. admonition:: Historical Note
- Given the purpose for which it's used, the name of this attribute
- (``use_for_related_fields``) might seem a little odd. Originally, the
- attribute only controlled the type of manager used for related field
- access, which is where the name came from. As it became clear the concept
- was more broadly useful, the name hasn't been changed. This is primarily
- so that existing code will :doc:`continue to work </misc/api-stability>` in
- future Django versions.
- Writing correct Managers for use in automatic Manager instances
- ---------------------------------------------------------------
- As already suggested by the :mod:`django.contrib.gis` example, above, the
- ``use_for_related_fields`` feature is primarily for managers that need to
- return a custom ``QuerySet`` subclass. In providing this functionality in your
- manager, there are a couple of things to remember.
- Do not filter away any results in this type of manager subclass
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- One reason an automatic manager is used is to access objects that are related
- to from some other model. In those situations, Django has to be able to see
- all the objects for the model it is fetching, so that *anything* which is
- referred to can be retrieved.
- If you override the ``get_queryset()`` method and filter out any rows, Django
- will return incorrect results. Don't do that. A manager that filters results
- in ``get_queryset()`` is not appropriate for use as an automatic manager.
- Set ``use_for_related_fields`` when you define the class
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The ``use_for_related_fields`` attribute must be set on the manager *class*, not
- on an *instance* of the class. The earlier example shows the correct way to set
- it, whereas the following will not work::
- # BAD: Incorrect code
- class MyManager(models.Manager):
- # ...
- pass
- # Sets the attribute on an instance of MyManager. Django will
- # ignore this setting.
- mgr = MyManager()
- mgr.use_for_related_fields = True
- class MyModel(models.Model):
- # ...
- objects = mgr
- # End of incorrect code.
- You also shouldn't change the attribute on the class object after it has been
- used in a model, since the attribute's value is processed when the model class
- is created and not subsequently reread. Set the attribute on the manager class
- when it is first defined, as in the initial example of this section and
- everything will work smoothly.
|