Django antipatterns 〉antipattern 〉(Over)use of .values() Fork me on GitHub

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:

  1. validation of fields;
  2. mapping the field to its representation with get_fieldname_display
  3. properties added on the model;
  4. retrieve related model objects (ForeignKeys act like lazy queries); and
  5. 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.