Commit 70e59aea authored by Malcolm Tredinnick's avatar Malcolm Tredinnick
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
parent 499f0184
Loading
Loading
Loading
Loading
+17 −16
Original line number Diff line number Diff line
@@ -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.
	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.
	   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.
	   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.
+20 −4
Original line number Diff line number Diff line
@@ -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
~~~~~