mirror of
https://github.com/django/django.git
synced 2025-09-26 12:09:19 +00:00
Fixed #26207 -- Replaced dynamic classes with non-data descriptors for deferred instance loading.
This commit is contained in:
parent
dac075e910
commit
7f51876f99
17 changed files with 104 additions and 240 deletions
|
@ -73,13 +73,12 @@ when loading from the database.
|
|||
The ``db`` argument contains the database alias for the database the model
|
||||
is loaded from, ``field_names`` contains the names of all loaded fields, and
|
||||
``values`` contains the loaded values for each field in ``field_names``. The
|
||||
``field_names`` are in the same order as the ``values``, so it is possible to
|
||||
use ``cls(**(zip(field_names, values)))`` to instantiate the object. If all
|
||||
of the model's fields are present, then ``values`` are guaranteed to be in
|
||||
the order ``__init__()`` expects them. That is, the instance can be created
|
||||
by ``cls(*values)``. It is possible to check if all fields are present by
|
||||
consulting ``cls._deferred`` - if ``False``, then all fields have been loaded
|
||||
from the database.
|
||||
``field_names`` are in the same order as the ``values``. If all of the model's
|
||||
fields are present, then ``values`` are guaranteed to be in the order
|
||||
``__init__()`` expects them. That is, the instance can be created by
|
||||
``cls(*values)``. If any fields are deferred, they won't appear in
|
||||
``field_names``. In that case, assign a value of ``django.db.models.DEFERRED``
|
||||
to each of the missing fields.
|
||||
|
||||
In addition to creating the new model, the ``from_db()`` method must set the
|
||||
``adding`` and ``db`` flags in the new instance's ``_state`` attribute.
|
||||
|
@ -87,14 +86,20 @@ In addition to creating the new model, the ``from_db()`` method must set the
|
|||
Below is an example showing how to record the initial values of fields that
|
||||
are loaded from the database::
|
||||
|
||||
from django.db.models import DEFERRED
|
||||
|
||||
@classmethod
|
||||
def from_db(cls, db, field_names, values):
|
||||
# default implementation of from_db() (could be replaced
|
||||
# with super())
|
||||
if cls._deferred:
|
||||
instance = cls(**zip(field_names, values))
|
||||
else:
|
||||
instance = cls(*values)
|
||||
# Default implementation of from_db() (subject to change and could
|
||||
# be replaced with super()).
|
||||
if len(values) != len(cls._meta.concrete_fields):
|
||||
values = list(values)
|
||||
values.reverse()
|
||||
values = [
|
||||
values.pop() if f.attname in field_names else DEFERRED
|
||||
for f in cls._meta.concrete_fields
|
||||
]
|
||||
new = cls(*values)
|
||||
instance._state.adding = False
|
||||
instance._state.db = db
|
||||
# customization to store the original field values on the instance
|
||||
|
@ -114,6 +119,12 @@ The example above shows a full ``from_db()`` implementation to clarify how that
|
|||
is done. In this case it would of course be possible to just use ``super()`` call
|
||||
in the ``from_db()`` method.
|
||||
|
||||
.. versionchanged:: 1.10
|
||||
|
||||
In older versions, you could check if all fields were loaded by consulting
|
||||
``cls._deferred``. This attribute is removed and
|
||||
``django.db.models.DEFERRED`` is new.
|
||||
|
||||
Refreshing objects from database
|
||||
================================
|
||||
|
||||
|
|
|
@ -783,6 +783,12 @@ Miscellaneous
|
|||
Web servers already implement this behavior. Responses retrieved using the
|
||||
Django test client continue to have these "response fixes" applied.
|
||||
|
||||
* ``Model.__init__()`` now receives ``django.db.models.DEFERRED`` as the value
|
||||
of deferred fields.
|
||||
|
||||
* The ``Model._deferred`` attribute is removed as dynamic model classes when
|
||||
using ``QuerySet.defer()`` and ``only()`` is removed.
|
||||
|
||||
.. _deprecated-features-1.10:
|
||||
|
||||
Features deprecated in 1.10
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue