From 1b646e656e46909af447056b4f98b9744aae4978 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sat, 15 Dec 2012 20:13:45 +0800 Subject: [PATCH] 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. --- docs/releases/1.5.txt | 15 +++++++++++++++ docs/topics/db/managers.txt | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt index 1d4a2a93b4..6ac5120617 100644 --- a/docs/releases/1.5.txt +++ b/docs/releases/1.5.txt @@ -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 +`. 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/topics/db/managers.txt b/docs/topics/db/managers.txt index eda6f9dac0..a14616a17c 100644 --- a/docs/topics/db/managers.txt +++ b/docs/topics/db/managers.txt @@ -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 -----------------------