2008-08-23 22:25:40 +00:00
|
|
|
|
========
|
|
|
|
|
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.
|
|
|
|
|
|
2010-08-19 19:27:44 +00:00
|
|
|
|
The way ``Manager`` classes work is documented in :doc:`/topics/db/queries`;
|
2009-03-24 11:40:12 +00:00
|
|
|
|
this document specifically touches on model options that customize ``Manager``
|
2008-08-23 22:25:40 +00:00
|
|
|
|
behavior.
|
|
|
|
|
|
2009-03-15 03:42:08 +00:00
|
|
|
|
.. _manager-names:
|
|
|
|
|
|
2008-08-23 22:25:40 +00:00
|
|
|
|
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:
|
|
|
|
|
|
2016-01-24 21:26:11 +00:00
|
|
|
|
Custom managers
|
2008-08-23 22:25:40 +00:00
|
|
|
|
===============
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2016-01-24 21:26:11 +00:00
|
|
|
|
Adding extra manager methods
|
2008-08-23 22:25:40 +00:00
|
|
|
|
----------------------------
|
|
|
|
|
|
|
|
|
|
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::
|
|
|
|
|
|
2013-05-18 10:12:26 +00:00
|
|
|
|
from django.db import models
|
|
|
|
|
|
2008-08-23 22:25:40 +00:00
|
|
|
|
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
|
2013-03-31 07:40:44 +00:00
|
|
|
|
GROUP BY p.id, p.question, p.poll_date
|
|
|
|
|
ORDER BY p.poll_date DESC""")
|
2008-08-23 22:25:40 +00:00
|
|
|
|
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):
|
2015-07-22 14:43:21 +00:00
|
|
|
|
poll = models.ForeignKey(OpinionPoll, on_delete=models.CASCADE)
|
2008-08-23 22:25:40 +00:00
|
|
|
|
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.
|
|
|
|
|
|
2016-01-24 21:26:11 +00:00
|
|
|
|
Modifying a manager's initial ``QuerySet``
|
|
|
|
|
------------------------------------------
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
2013-08-05 16:23:26 +00:00
|
|
|
|
A ``Manager``’s base ``QuerySet`` returns all objects in the system. For
|
2008-08-23 22:25:40 +00:00
|
|
|
|
example, using this model::
|
|
|
|
|
|
2013-05-18 10:12:26 +00:00
|
|
|
|
from django.db import models
|
|
|
|
|
|
2008-08-23 22:25:40 +00:00
|
|
|
|
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.
|
|
|
|
|
|
2013-08-05 16:23:26 +00:00
|
|
|
|
You can override a ``Manager``’s base ``QuerySet`` by overriding the
|
2013-03-08 14:15:23 +00:00
|
|
|
|
``Manager.get_queryset()`` method. ``get_queryset()`` should return a
|
2008-08-23 22:25:40 +00:00
|
|
|
|
``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):
|
2013-03-08 14:15:23 +00:00
|
|
|
|
def get_queryset(self):
|
|
|
|
|
return super(DahlBookManager, self).get_queryset().filter(author='Roald Dahl')
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
|
|
|
|
# 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.
|
|
|
|
|
|
2013-03-08 14:15:23 +00:00
|
|
|
|
Of course, because ``get_queryset()`` returns a ``QuerySet`` object, you can
|
2008-08-23 22:25:40 +00:00
|
|
|
|
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::
|
|
|
|
|
|
2014-02-03 03:00:48 +00:00
|
|
|
|
class AuthorManager(models.Manager):
|
2013-03-08 14:15:23 +00:00
|
|
|
|
def get_queryset(self):
|
2014-02-03 03:00:48 +00:00
|
|
|
|
return super(AuthorManager, self).get_queryset().filter(role='A')
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
2014-02-03 03:00:48 +00:00
|
|
|
|
class EditorManager(models.Manager):
|
2013-03-08 14:15:23 +00:00
|
|
|
|
def get_queryset(self):
|
2014-02-03 03:00:48 +00:00
|
|
|
|
return super(EditorManager, self).get_queryset().filter(role='E')
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
|
|
|
|
class Person(models.Model):
|
|
|
|
|
first_name = models.CharField(max_length=50)
|
|
|
|
|
last_name = models.CharField(max_length=50)
|
2014-02-03 03:00:48 +00:00
|
|
|
|
role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor'))))
|
2008-08-23 22:25:40 +00:00
|
|
|
|
people = models.Manager()
|
2014-02-03 03:00:48 +00:00
|
|
|
|
authors = AuthorManager()
|
|
|
|
|
editors = EditorManager()
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
2014-02-03 03:00:48 +00:00
|
|
|
|
This example allows you to request ``Person.authors.all()``, ``Person.editors.all()``,
|
2008-08-23 22:25:40 +00:00
|
|
|
|
and ``Person.people.all()``, yielding predictable results.
|
|
|
|
|
|
2014-10-05 01:09:32 +00:00
|
|
|
|
.. _default-managers:
|
|
|
|
|
|
|
|
|
|
Default managers
|
2016-04-17 11:55:55 +00:00
|
|
|
|
----------------
|
|
|
|
|
|
|
|
|
|
.. attribute:: Model._default_manager
|
2014-10-05 01:09:32 +00:00
|
|
|
|
|
2010-04-06 11:52:32 +00:00
|
|
|
|
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
|
2016-04-17 11:55:55 +00:00
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
You can specify a custom default manager using :attr:`Meta.base_manager_name
|
|
|
|
|
<django.db.models.Options.base_manager_name>`.
|
|
|
|
|
|
|
|
|
|
If you're writing some code that must handle an unknown model, for example, in
|
|
|
|
|
a third-party app that implements a generic view, use this manager (or
|
|
|
|
|
:attr:`~Model._base_manager`) rather than assuming the model has an ``objects``
|
|
|
|
|
manager.
|
|
|
|
|
|
|
|
|
|
Base managers
|
|
|
|
|
-------------
|
|
|
|
|
|
|
|
|
|
.. attribute:: Model._base_manager
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
2009-03-15 03:42:08 +00:00
|
|
|
|
.. _managers-for-related-objects:
|
|
|
|
|
|
2008-08-23 22:25:40 +00:00
|
|
|
|
Using managers for related object access
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
2016-04-17 11:55:55 +00:00
|
|
|
|
By default, Django uses an instance of the ``Model._base_manager`` 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.
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
2016-04-17 11:55:55 +00:00
|
|
|
|
If the normal base manager class (:class:`django.db.models.Manager`) isn't
|
|
|
|
|
appropriate for your circumstances, you can tell Django which class to use by
|
|
|
|
|
setting :attr:`Meta.base_manager_name
|
|
|
|
|
<django.db.models.Options.base_manager_name>`.
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
2016-04-17 11:55:55 +00:00
|
|
|
|
Don't filter away any results in this type of manager subclass
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
|
|
This manager is used 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 a default manager.
|
2008-09-02 09:04:54 +00:00
|
|
|
|
|
2013-07-26 08:59:40 +00:00
|
|
|
|
.. _calling-custom-queryset-methods-from-manager:
|
|
|
|
|
|
2016-01-24 21:26:11 +00:00
|
|
|
|
Calling custom ``QuerySet`` methods from the manager
|
|
|
|
|
----------------------------------------------------
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
|
|
|
|
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):
|
2014-02-03 03:00:48 +00:00
|
|
|
|
def authors(self):
|
|
|
|
|
return self.filter(role='A')
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
2014-02-03 03:00:48 +00:00
|
|
|
|
def editors(self):
|
|
|
|
|
return self.filter(role='E')
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
|
|
|
|
class PersonManager(models.Manager):
|
|
|
|
|
def get_queryset(self):
|
2013-12-05 00:03:28 +00:00
|
|
|
|
return PersonQuerySet(self.model, using=self._db)
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
2014-02-03 03:00:48 +00:00
|
|
|
|
def authors(self):
|
|
|
|
|
return self.get_queryset().authors()
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
2014-02-03 03:00:48 +00:00
|
|
|
|
def editors(self):
|
|
|
|
|
return self.get_queryset().editors()
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
|
|
|
|
class Person(models.Model):
|
|
|
|
|
first_name = models.CharField(max_length=50)
|
|
|
|
|
last_name = models.CharField(max_length=50)
|
2014-02-03 03:00:48 +00:00
|
|
|
|
role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor'))))
|
2013-07-26 08:59:40 +00:00
|
|
|
|
people = PersonManager()
|
|
|
|
|
|
2014-02-03 03:00:48 +00:00
|
|
|
|
This example allows you to call both ``authors()`` and ``editors()`` directly from
|
2013-07-26 08:59:40 +00:00
|
|
|
|
the manager ``Person.people``.
|
|
|
|
|
|
|
|
|
|
.. _create-manager-with-queryset-methods:
|
|
|
|
|
|
2016-01-24 21:26:11 +00:00
|
|
|
|
Creating a manager with ``QuerySet`` methods
|
|
|
|
|
--------------------------------------------
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
|
|
|
|
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
|
2013-08-05 16:23:26 +00:00
|
|
|
|
of ``Manager`` with a copy of a custom ``QuerySet``’s methods::
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
|
|
|
|
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.
|
2013-08-15 11:14:10 +00:00
|
|
|
|
- Methods with a ``queryset_only`` attribute set to ``False`` are always copied.
|
|
|
|
|
- Methods with a ``queryset_only`` attribute set to ``True`` are never copied.
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2016-01-24 21:26:11 +00:00
|
|
|
|
``from_queryset()``
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
|
|
|
|
.. classmethod:: from_queryset(queryset_class)
|
|
|
|
|
|
2014-09-29 03:40:31 +00:00
|
|
|
|
For advanced usage you might want both a custom ``Manager`` and a custom
|
2013-07-26 08:59:40 +00:00
|
|
|
|
``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 manager_only_method(self):
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
class CustomQuerySet(models.QuerySet):
|
|
|
|
|
def manager_and_queryset_method(self):
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
class MyModel(models.Model):
|
2015-11-27 18:49:35 +00:00
|
|
|
|
objects = BaseManager.from_queryset(CustomQuerySet)()
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
|
|
|
|
You may also store the generated class into a variable::
|
|
|
|
|
|
2015-11-27 18:49:35 +00:00
|
|
|
|
CustomManager = BaseManager.from_queryset(CustomQuerySet)
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
|
|
|
|
class MyModel(models.Model):
|
2014-07-01 18:20:54 +00:00
|
|
|
|
objects = CustomManager()
|
2013-07-26 08:59:40 +00:00
|
|
|
|
|
2009-03-18 09:47:08 +00:00
|
|
|
|
.. _custom-managers-and-inheritance:
|
|
|
|
|
|
2008-09-02 09:04:54 +00:00
|
|
|
|
Custom managers and model inheritance
|
|
|
|
|
-------------------------------------
|
|
|
|
|
|
2016-04-17 11:55:55 +00:00
|
|
|
|
Here's how Django handles custom managers and :ref:`model inheritance
|
|
|
|
|
<model-inheritance>`:
|
2008-09-02 09:04:54 +00:00
|
|
|
|
|
2016-04-17 11:55:55 +00:00
|
|
|
|
#. Managers from base classes are always inherited by the child class,
|
2016-02-18 19:27:55 +00:00
|
|
|
|
using Python's normal name resolution order (names on the child
|
2011-10-14 00:12:01 +00:00
|
|
|
|
class override all others; then come names on the first parent class,
|
2016-02-18 19:27:55 +00:00
|
|
|
|
and so on).
|
|
|
|
|
|
2016-04-17 11:55:55 +00:00
|
|
|
|
#. If no managers are declared on a model and/or its parents, Django
|
|
|
|
|
automatically creates the ``objects`` manager.
|
|
|
|
|
|
|
|
|
|
#. The default manager on a class is either the one chosen with
|
|
|
|
|
:attr:`Meta.default_manager_name
|
|
|
|
|
<django.db.models.Options.default_manager_name>`, or the first manager
|
|
|
|
|
declared on the model, or the default manager of the first parent model.
|
2016-02-18 19:27:55 +00:00
|
|
|
|
|
|
|
|
|
.. versionchanged:: 1.10
|
|
|
|
|
|
|
|
|
|
In older versions, manager inheritance varied depending on the type of
|
|
|
|
|
model inheritance (i.e. :ref:`abstract-base-classes`,
|
|
|
|
|
:ref:`multi-table-inheritance`, or :ref:`proxy-models`), especially
|
|
|
|
|
with regards to electing the default manager.
|
2008-09-02 09:04:54 +00:00
|
|
|
|
|
2009-03-15 03:42:31 +00:00
|
|
|
|
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):
|
2013-05-18 10:12:26 +00:00
|
|
|
|
# ...
|
2010-02-22 02:35:47 +00:00
|
|
|
|
objects = CustomManager()
|
2009-03-15 03:42:31 +00:00
|
|
|
|
|
|
|
|
|
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):
|
2013-05-18 10:12:26 +00:00
|
|
|
|
# ...
|
2009-03-15 03:42:31 +00:00
|
|
|
|
# This class has CustomManager as the default manager.
|
2013-05-18 10:12:26 +00:00
|
|
|
|
pass
|
2009-03-15 03:42:31 +00:00
|
|
|
|
|
|
|
|
|
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):
|
2013-05-18 10:12:26 +00:00
|
|
|
|
# ...
|
2009-03-15 03:42:31 +00:00
|
|
|
|
# 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):
|
2013-05-18 10:12:26 +00:00
|
|
|
|
# ...
|
2009-03-15 03:42:31 +00:00
|
|
|
|
# Default manager is CustomManager, but OtherManager is
|
|
|
|
|
# also available via the "extra_manager" attribute.
|
2013-05-18 10:12:26 +00:00
|
|
|
|
pass
|
2009-03-15 03:42:31 +00:00
|
|
|
|
|
2012-12-15 12:13:45 +00:00
|
|
|
|
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.
|
|
|
|
|
|
2011-01-16 06:44:23 +00:00
|
|
|
|
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.
|