Often in views, one can find code that looks like:
from django.shortcuts import render
def some_view(request):
my_objects = MyModel.objects.values()
return render(request, 'some_template.html', {'my_objects': my_objects})
The .values(…)
[Django-doc] part will return a (QuerySet
) of dictionaries, not MyModel
objects.
Why is it a problem?
Dictionaries are less "rich". These simply map keys to values. A model enhances that with several extra functionalities:
- validation of fields;
- mapping the field to its representation with
get_fieldname_display
; - properties added on the model;
- retrieve related model objects (
ForeignKey
s act like lazy queries); and - updating, removing, etc. of the model to the database.
These are typical problems that arise by the primitive obsession antipattern [refactoring.guru].
How can we fix this?
Do not make use of .values(…)
unless in certain circumstances. One can make use of .values(…)
for example to group by a certain value. But normally using .values()
is not a good idea, one thus better creates a query that looks like:
from django.shortcuts import render
def some_view(request):
my_objects = MyModel.objects.all()
return render(request, 'some_template.html', {'my_objects': my_objects})
Extra tips
Sometimes people make use of .values(…)
to boost queries, by only selecting columns they are interested in. One can make use of .only(…)
[Django-doc] and .defer(…)
[Django-doc] to retrieve only a subset of the columns of the model. The remaining columns are then lazy loaded with extra queries when necessary.
Some people use .values(…)
to serialize data to a JSON blob. Usually it is better to make use of serializers [drf-doc] that are for example offered by the Django REST framework package. These serializers allow to serialize related model objects, can do more sophisticated serialization, and often work in both directions: converting a model object to a serialized form, and deserializing objects into model objects. This will thus reduce the amount of work and do proper validation.