2
0
Эх сурвалжийг харах

Be very clear about when it's appropriate to use defer() and only().

I've been seeing a bit of over-reliance on defer() and only() in code
around the place and it's generally better modelled with normalised data
or shadow (unmanaged) models. This commit makes this position clearer.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16692 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Malcolm Tredinnick 13 жил өмнө
parent
commit
70e59aeaf8

+ 17 - 16
docs/ref/models/options.txt

@@ -91,7 +91,8 @@ Django quotes column and table names behind the scenes.
 
 
     Defaults to ``True``, meaning Django will create the appropriate database
     Defaults to ``True``, meaning Django will create the appropriate database
     tables in :djadmin:`syncdb` and remove them as part of a :djadmin:`reset`
     tables in :djadmin:`syncdb` and remove them as part of a :djadmin:`reset`
-    management command. That is, Django *manages* the database tables' lifecycles.
+    management command. That is, Django *manages* the database tables'
+    lifecycles.
 
 
     If ``False``, no database table creation or deletion operations will be
     If ``False``, no database table creation or deletion operations will be
     performed for this model. This is useful if the model represents an existing
     performed for this model. This is useful if the model represents an existing
@@ -99,21 +100,21 @@ Django quotes column and table names behind the scenes.
     the *only* difference when ``managed=False``. All other aspects of
     the *only* difference when ``managed=False``. All other aspects of
     model handling are exactly the same as normal. This includes
     model handling are exactly the same as normal. This includes
 
 
-        1. Adding an automatic primary key field to the model if you don't declare
-           it.  To avoid confusion for later code readers, it's recommended to
-           specify all the columns from the database table you are modeling when
-           using unmanaged models.
-
-        2. If a model with ``managed=False`` contains a
-           :class:`~django.db.models.ManyToManyField` that points to another
-           unmanaged model, then the intermediate table for the many-to-many join
-           will also not be created. However, the intermediary table between one
-           managed and one unmanaged model *will* be created.
-
-           If you need to change this default behavior, create the intermediary
-           table as an explicit model (with ``managed`` set as needed) and use the
-           :attr:`ManyToManyField.through` attribute to make the relation use your
-           custom model.
+	1. Adding an automatic primary key field to the model if you don't
+	   declare it.  To avoid confusion for later code readers, it's
+	   recommended to specify all the columns from the database table you
+	   are modeling when using unmanaged models.
+
+	2. If a model with ``managed=False`` contains a
+	   :class:`~django.db.models.ManyToManyField` that points to another
+	   unmanaged model, then the intermediate table for the many-to-many
+	   join will also not be created. However, the intermediary table
+	   between one managed and one unmanaged model *will* be created.
+
+	   If you need to change this default behavior, create the intermediary
+	   table as an explicit model (with ``managed`` set as needed) and use
+	   the :attr:`ManyToManyField.through` attribute to make the relation
+	   use your custom model.
 
 
     For tests involving models with ``managed=False``, it's up to you to ensure
     For tests involving models with ``managed=False``, it's up to you to ensure
     the correct tables are created as part of the test setup.
     the correct tables are created as part of the test setup.

+ 20 - 4
docs/ref/models/querysets.txt

@@ -139,7 +139,7 @@ Though you usually won't create one manually -- you'll go through a
         clause or a default ordering on the model. ``False`` otherwise.
         clause or a default ordering on the model. ``False`` otherwise.
 
 
     .. attribute:: db
     .. attribute:: db
-    
+
         The database that will be used if this query is executed now.
         The database that will be used if this query is executed now.
 
 
     .. note::
     .. note::
@@ -906,9 +906,21 @@ eventually).
     analyzed your queries closely and understand *exactly* what information
     analyzed your queries closely and understand *exactly* what information
     you need and have measured that the difference between returning the
     you need and have measured that the difference between returning the
     fields you need and the full set of fields for the model will be
     fields you need and the full set of fields for the model will be
-    significant. When you are initially developing your applications, don't
-    bother using ``defer()``; leave it until your query construction has
-    settled down and you understand where the hot-points are.
+    significant.
+
+    Even if you think you are in the advanced use-case situation, **only use
+    defer() when you cannot, at queryset load time, determine if you will need
+    the extra fields or not**. If you are frequently loading and using a
+    particular subset of your data, the best choice you can make is to
+    normalize your models and put the non-loaded data into a separate model
+    (and database table). If the columns *must* stay in the one table for some
+    reason, create a model with ``Meta.managed = False`` (see the
+    :py:attr:`managed attribute <django.db.models.Options.managed>`
+    documentation) containing just the fields you normally need to load and use
+    that where you might otherwise call ``defer()``. This makes your code more
+    explicit to the reader, is slightly faster and consumes a little less
+    memory in the Python process.
+
 
 
 only
 only
 ~~~~
 ~~~~
@@ -946,6 +958,10 @@ logically::
     # existing set of fields).
     # existing set of fields).
     Entry.objects.defer("body").only("headline", "body")
     Entry.objects.defer("body").only("headline", "body")
 
 
+All of the cautions in the note for the :py:meth:`defer` documentation apply to
+``only()`` as well. Use it cautiously and only after exhausting your other
+options.
+
 using
 using
 ~~~~~
 ~~~~~