Django - 使用 select_related() 优化查询

srj*_*jio 3 django django-queryset django-select-related

我有以下型号。

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')
Run Code Online (Sandbox Code Playgroud)

我想选择拥有汽车的司机的姓名。

Car.objects.all().values('owner__name')
Run Code Online (Sandbox Code Playgroud)

我是否需要使用 select_related() 方法来避免每个对象的连接,或者它是多余的,因为 values() 方法是隐式的?

Car.objects.all().select_related('owner').values('owner__name')
Run Code Online (Sandbox Code Playgroud)

同样,这次我想要拥有汽车的司机的国家名称。哪一个是最好的?

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')
Run Code Online (Sandbox Code Playgroud)

Rem*_*ich 5

首先,.all()可以删除示例中所有出现的;manager( .objects) 已经拥有 QuerySet 的几乎所有方法,除了.delete().

.select_related仅当您的最终查询返回模型实例时才有帮助;然后,每个实例的所有外键都将被预加载。

但是,如果您正在使用,.values您将获得字典,并且没有要预加载的外键属性。所以在这种情况下不应该使用它。

当您执行.values('owner__name')Django 时,它已经看到它需要加入所有者和汽车,因此不会进行额外的查询。

在最后一个你想要国家,所以使用 Country.objects:

Country.objects.filter(driver__car__isnull=False).values('name')
Run Code Online (Sandbox Code Playgroud)