Django: understanding .values() and .values_list() use cases

Viewed 8490

I'm having trouble understanding under what circumstances are .values() or .values_list() better than just using Model instances?

I think the following are all equivalent:

results = SomeModel.objects.all()
for result in results:
    print(result.some_field)

results = SomeModel.objects.all().values()
for result in results:
    print(result['some_field'])

results = SomeModel.objects.all().values_list()
for some_field, another_field in results:
    print(some_field)

obviously these are stupid examples, could anyone point out a good reason for using .values() / .values_list() over just using Model instances directly?

edit :

I did some simple profiling, using a noddy model that contained 2 CharField(max_length=100) Iterating over just 500 instances to copy 'first' to another variable, taking the average of 200 runs I got following results:

 Test.objects.all()                                  time: 0.010061947107315063
 Test.objects.all().values('first')                  time: 0.00578328013420105
 Test.objects.all().values_list('first')             time: 0.005257354974746704
 Test.objects.all().values_list('first', flat=True)  time: 0.0052023959159851075
 Test.objects.all().only('first')                    time: 0.011166254281997681

So the answer is definitively : performance! (mostly, see knbk answer below)

3 Answers

I use "values_list()" to create a Custom Dropdown Single Select Box for Django Admin as shown below:

# "admin.py"

from django.contrib import admin
from django import forms
from .models import Favourite, Food, Fruit, Vegetable

class FoodForm(forms.ModelForm):
                                # Here
    FRUITS = Fruit.objects.all().values_list('id', 'name')
    fruits = forms.ChoiceField(choices=FRUITS)

                                        # Here
    VEGETABLES = Vegetable.objects.all().values_list('id', 'name')
    vegetables = forms.ChoiceField(choices=VEGETABLES)
    
class FoodInline(admin.TabularInline):
    model = Food
    form = FoodForm

@admin.register(Favourite)
class FavouriteAdmin(admin.ModelAdmin):
    inlines = [FoodInline]
Related