Deferred Fields in Django
Django’s ORM provides a way to load only specific fields from the database using
only
and defer
methods. The deferred fields are represented with
the django.db.models.base.DEFERRED
object.
refresh_from_db
model loads the deferred fields from the database, but
it is possible to make it load only specific fields.
While working on the openwisp-controller, I learn the shenanigans of deferred fields. openwisp-controller needs to emit signals when some specific fields are implemented. Some of these fields are sometimes deferred, hence I had to write special code to fetch these fields from the database if they are no longer deferred. What does that mean? Let me explain it through an example.
Consider a Django model Person
containing two fields, name and age.
Now, you queried this model loading only the name
field
first_person = Person.objects.only('name').first()
This makes the age
field deferred. How can you check this? Well, if you
access the age
field as first_person.age
, Django will fetch the value
from the database for you. Therefore, a special method get_deferred_fields()
is provided which returns a set of deferred fields for the instance of the
model.
Executing first_person.get_deferred_fields()
should return {'age'}
. But
if you assign a value to the age attribute like first_person.age = 99
, you
will get an empty set from first_person.get_deferred_fields()
signalling that there are no deferred fields of first_person
instance.
Following pages Django’s documentation describe deferred fields well:
- https://docs.djangoproject.com/en/3.2/ref/models/querysets/
- https://docs.djangoproject.com/en/3.2/ref/models/instances/