Fixed #7154 -- Inherit all model managers from abstract base classes.

Also added documentation describing how manager inheritance works (and when
manager aren't inherited). Based on some patches from sebastian_noack and
emulbreh.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@8851 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-09-02 09:04:54 +00:00
parent cf5087fdb2
commit f31425e8e2
6 changed files with 211 additions and 9 deletions

View file

@ -189,3 +189,35 @@ attributes by giving it a ``use_for_related_fields`` property::
...
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 behaviour 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.