Skip to content

Commit

Permalink
[1.5.X] Fixed #19384 -- Documented the behavior of custom managers on…
Browse files Browse the repository at this point in the history
… abstract models.

This documents the behavior introduced by cc337a7, which is BACKWARDS
INCOMPATIBLE for any attempt to invoke a method on a manager using the
abstract class as the calling class (e.g., AbstractBase.objects.do_something())

Thanks to mhsparks for the report.

Backport of 1b646e6 from master.
  • Loading branch information
freakboy3742 committed Dec 15, 2012
1 parent 084a8e2 commit 9cf5662
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
15 changes: 15 additions & 0 deletions docs/releases/1.5.txt
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,21 @@ Backwards incompatible changes in 1.5
deprecation timeline for a given feature, its removal may appear as a
backwards incompatible change.

Managers on abstract models
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Abstract models are able to define a custom manager, and that manager
:ref:`will be inherited by any concrete models extending the abstract model
<custom-managers-and-inheritance>`. However, if you try to use the abstract
model to call a method on the manager, an exception will now be raised.
Previously, the call would have been permitted, but would have failed as soon
as any database operation was attempted (usually with a "table does not exist"
error from the database).

If you have functionality on a manager that you have been invoking using
the abstract class, you should migrate that logic to a Python
``staticmethod`` or ``classmethod`` on the abstract class.

Context in year archive class-based views
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
15 changes: 15 additions & 0 deletions docs/topics/db/managers.txt
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,21 @@ it into the inheritance hierarchy *after* the defaults::
# Default manager is CustomManager, but OtherManager is
# also available via the "extra_manager" attribute.

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
-----------------------

Expand Down

0 comments on commit 9cf5662

Please sign in to comment.