Fixed #19384 -- Documented the behavior of custom managers on abstract models.
This documents the behavior introduced by cc337a74
, 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.
This commit is contained in:
parent
1e5b0fc4d0
commit
1b646e656e
|
@ -341,6 +341,21 @@ Backwards incompatible changes in 1.5
|
||||||
deprecation timeline for a given feature, its removal may appear as a
|
deprecation timeline for a given feature, its removal may appear as a
|
||||||
backwards incompatible change.
|
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
|
Context in year archive class-based views
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -274,6 +274,21 @@ it into the inheritance hierarchy *after* the defaults::
|
||||||
# Default manager is CustomManager, but OtherManager is
|
# Default manager is CustomManager, but OtherManager is
|
||||||
# also available via the "extra_manager" attribute.
|
# 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
|
Implementation concerns
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue