Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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
  • Loading branch information...
commit 70e59aeaf85161ed26044c000a43af46719265ad 1 parent 499f018
@malcolmt malcolmt authored
Showing with 37 additions and 20 deletions.
  1. +17 −16 docs/ref/models/options.txt
  2. +20 −4 docs/ref/models/querysets.txt
View
33 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
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
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
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
the correct tables are created as part of the test setup.
View
24 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.
.. attribute:: db
-
+
The database that will be used if this query is executed now.
.. note::
@@ -906,9 +906,21 @@ eventually).
analyzed your queries closely and understand *exactly* what information
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
- 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
~~~~
@@ -946,6 +958,10 @@ logically::
# existing set of fields).
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
~~~~~
Please sign in to comment.
Something went wrong with that request. Please try again.