Author: mtredinnick
Date: 2009-03-14 22:45:56 -0500 (Sat, 14 Mar 2009)
New Revision: 10060

Modified:
   django/branches/releases/1.0.X/docs/topics/db/managers.txt
Log:
[1.0.X] Clarified and expanded documentation for Manager.use_for_related_fields.

This is for Manager subclasses that are default managers, but only
sometimes.  The general rule is: "don't use it." If you really need it,
read the instructions.

Backport of r10057 from trunk.

Modified: django/branches/releases/1.0.X/docs/topics/db/managers.txt
===================================================================
--- django/branches/releases/1.0.X/docs/topics/db/managers.txt  2009-03-15 
03:45:32 UTC (rev 10059)
+++ django/branches/releases/1.0.X/docs/topics/db/managers.txt  2009-03-15 
03:45:56 UTC (rev 10060)
@@ -16,6 +16,8 @@
 document specifically touches on model options that customize ``Manager``
 behavior.
 
+.. _manager-names:
+
 Manager names
 =============
 
@@ -175,20 +177,23 @@
 avoid a situation where overriding of ``get_query_set()`` results in
 an inability to retrieve objects you'd like to work with.
 
+.. _managers-for-related-objects:
+
 Using managers for related object access
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-By default, Django uses a "bare" (i.e. default) manager when accessing related
-objects (i.e. ``choice.poll``). If this default isn't appropriate for your
-default manager, you can force Django to use a custom manager for related 
object
-attributes by giving it a ``use_for_related_fields`` property::
+By default, Django uses an instance of a "plain" 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.
 
-    class MyManager(models.Manager)::
-        use_for_related_fields = True
-        ...
-        
+If the normal plain manager class (:class:`django.db.models.Manager`) is not
+appropriate for your circumstances, you can force Django to use the same class
+as the default manager for your model by setting the `use_for_related_fields`
+attribute on the manager class. This is documented fully below_.
 
-        ...
+.. _below: manager-types_
 
 Custom managers and model inheritance
 -------------------------------------
@@ -221,3 +226,103 @@
        manager is explicitly declared, Django's normal default manager is
        used.
 
+.. _manager-types:
+
+Controlling Automatic Manager Types
+===================================
+
+This document has already mentioned a couple of places where Django creates a
+manager class for you: `default managers`_ and the "plain" manager used to
+`access related objects`_. There are other places in the implementation of
+Django where temporary plain managers are needed. Those automatically created
+managers will normally be instances of the :class:`django.db.models.Manager`
+class.
+
+.. _default managers: manager-names_
+.. _access related objects: managers-for-related-objects_
+
+Throughout this section, we will use the term "automatic manager" to mean a
+manager that Django creates for you -- either as a default manager on a model
+with no managers, or to use temporarily when accessing related objects.
+
+Sometimes this default class won't be the right choice. One example is in the
+`django.contrib.gis` application that ships with Django itself. All `gis`
+models must use a special manager class (``GeoManager``) because they need a
+special queryset (``GeoQuerySet``) to be used for interacting with the
+database.  It turns out that models which require a special manager like this
+need to use the same manager class wherever an automatic manager is created.
+
+Django provides a way for custom manager developers to say that their manager
+class should be used for automatic managers whenever it is the default manager
+on a model. This is done by setting the ``use_for_related_fields`` attribute on
+the manager class::
+
+    class MyManager(models.Manager):
+        use_for_related_fields = True
+
+        ...
+
+If this attribute is set on the *default* manager for a model (only the
+default manager is considered in these situations), Django will use that class
+whenever it needs to automatically create a manager for the class.  Otherwise,
+it will use :class:`django.db.models.Manager`.
+
+.. admonition:: Historical Note
+
+    Given the purpose for which it's used, the name of this attribute
+    (``use_for_related_fields``) might seem a little odd. Originally, the
+    attribute only controlled the type of manager used for related field
+    access, which is where the name came from. As it became clear the concept
+    was more broadly useful, the name hasn't been changed. This is primarily
+    so that existing code will :ref:`continue to work <misc-api-stability>` in
+    future Django versions.
+
+Writing Correct Managers For Use In Automatic Manager Instances
+---------------------------------------------------------------
+
+As already suggested by the `django.contrib.gis` example, above, the
+``use_for_related_fields`` feature is primarily for managers that need to
+return a custom ``QuerySet`` subclass. In providing this functionality in your
+manager, there are a couple of things to be remember and that's the topic of
+this section.
+
+Do not filter away any results in this type of manager subclass
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+One reason an automatic manager is used is 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_query_set()`` method and filter out any rows, Django
+will return incorrect results. Don't do that. A manager that filters results
+in ``get_query_set()`` is not appropriate for use as an automatic manager.
+
+Set ``use_for_related_fields`` when you define the class
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``use_for_related_fields`` attribute must be set on the manager *class*,
+object not on an *instance* of the class. The earlier example shows the
+correct way to set it, whereas the following will not work::
+
+    # BAD: Incorrect code
+    class MyManager(models.Manager):
+        ...
+
+    # Sets the attribute on an instance of MyManager. Django will
+    # ignore this setting.
+    mgr = MyManager()
+    mgr.use_for_related_fields = True
+
+    class MyModel(models.Model):
+        ...
+        objects = mgr
+
+    # End of incorrect code.
+
+You also shouldn't change the attribute on the class object after it has been
+used in a model, since the attribute's value is processed when the model class
+is created and not subsequently reread. Set the attribute on the manager class
+when it is first defined, as in the initial example of this section and
+everything will work smoothly.
+


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to