srjjio
srjjio

Reputation: 1049

Django - Optimize queries with select_related()

I have the following model.

class Car(models.Model):
    owner = models.ForeignKey('Driver')

class Country(models.Model)
    name = models.CharField(max_length=255)

class Driver(models.Model):
    name = models.CharField(max_length=255)
    age = models.IntegerField()
    country = models.ForeignKey('Country')

I want to select the name of drivers owning a car.

Car.objects.all().values('owner__name')

Do I need to use select_related() method, to avoid a join for each object, or it is redundant because implicit with values() method?

Car.objects.all().select_related('owner').values('owner__name')

In the same way, I want, this time, the name of countries with drivers owning a car. Which one is the best?

Car.objects.all().values('owner__country__name')
Car.objects.all().select_related('owner', 'country').values('owner__country__name')
Car.objects.all().select_related('owner__country').values('owner__country__name')

Upvotes: 3

Views: 1292

Answers (1)

RemcoGerlich
RemcoGerlich

Reputation: 31260

First, all the occurrences of .all() in your examples can be deleted; the manager (.objects) already has almost all methods of the QuerySet, except for .delete().

.select_related is only helpful when your eventual query returns model instances; then, all the foreign key of each instance will be pre-loaded.

But if you are using .values you are getting dictionaries, and there are no foreign key attributes to pre-load. So it should not be used in that case.

When you do .values('owner__name') Django already sees that it needs to join owners and cars, no extra queries are done.

In the last one you want Countries, so use Country.objects:

Country.objects.filter(driver__car__isnull=False).values('name')

Upvotes: 6

Related Questions