Does queryset.values_list makes another call to db?

Viewed 329

Let's say I have an already evaluated queryset.

# queryset is evaluated here
queryset = MyModel.objects.filter(name="blabla")

for obj in queryset:
  # do some stuff

if I call .values_list on this queryset later on, does it make an extra call to the database or fetch the response from the queryset object cache?

obj_map = {k: v in queryset.values_list("id", "name")} # <- does it make a call?
2 Answers

Inspecting the queries generated after both statements shows that the database is hit a second time. Try this:

from django.db import connection


queryset = MyModel.objects.filter(name="blabla")

for obj in queryset:
  # do some stuff
print(len(connection.queries))
>>> 1
obj_map = {k: v in queryset.values_list("id", "name")}
print(len(connection.queries))
>>> 2

You can print(connection.queries) instead to see the actual queries being used.

According to the docs, the values_list function returns a subclass of queryset which clones most of the attributes of the original queryset.

When the queryset is evaluated, it fills its _result_cache attribute that is used for methods that does not create new querysets. If this value is None, it means the cache is empty. Also, According to the docs, the values_list function returns a subclass of queryset which clones most of the attributes of the original queryset. However, it doesn't copy the cache:

print(queryset._result_cache)
# [<MyModel: 0>, <MyModel: 2>, <MyModel: 2> ... ]

print(queryset.values_list("id", "name")._result_cache)
# Nothing

Related