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
This commit is contained in:
parent
499f01842e
commit
70e59aeaf8
|
@ -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
|
1. Adding an automatic primary key field to the model if you don't
|
||||||
it. To avoid confusion for later code readers, it's recommended to
|
declare it. To avoid confusion for later code readers, it's
|
||||||
specify all the columns from the database table you are modeling when
|
recommended to specify all the columns from the database table you
|
||||||
using unmanaged models.
|
are modeling when using unmanaged models.
|
||||||
|
|
||||||
2. If a model with ``managed=False`` contains a
|
2. If a model with ``managed=False`` contains a
|
||||||
:class:`~django.db.models.ManyToManyField` that points to another
|
:class:`~django.db.models.ManyToManyField` that points to another
|
||||||
unmanaged model, then the intermediate table for the many-to-many join
|
unmanaged model, then the intermediate table for the many-to-many
|
||||||
will also not be created. However, the intermediary table between one
|
join will also not be created. However, the intermediary table
|
||||||
managed and one unmanaged model *will* be created.
|
between one managed and one unmanaged model *will* be created.
|
||||||
|
|
||||||
If you need to change this default behavior, create the intermediary
|
If you need to change this default behavior, create the intermediary
|
||||||
table as an explicit model (with ``managed`` set as needed) and use the
|
table as an explicit model (with ``managed`` set as needed) and use
|
||||||
:attr:`ManyToManyField.through` attribute to make the relation use your
|
the :attr:`ManyToManyField.through` attribute to make the relation
|
||||||
custom model.
|
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.
|
||||||
|
|
|
@ -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
|
significant.
|
||||||
bother using ``defer()``; leave it until your query construction has
|
|
||||||
settled down and you understand where the hot-points are.
|
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
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue