2017-01-10 15 views
2

次のモデルがあります。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') 

車を所有しているドライバの名前を選択します。

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

は、私は、各オブジェクトのための参加を避けるために、select_related()メソッドを使用する必要がありますか、またはそれが値を持つ暗黙の理由()メソッド冗長ですか?

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

同じように、今度は車を所有しているドライバーがいる国の名前が必要です。どちらが最高ですか?

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') 
+0

最後の部分、私は 'あなたが' Driver.objects.filterを(car__isnull = Falseの、...)したいと仮定しますが、あなたの質問少し広いですが、暗黙的な結合についての最初の質問に制限する必要があります – Sayse

+1

ありがとう、私はselect_related()の使用にスコープを減らすために質問を編集します。 – srjjio

答えて

2

最初に、例ではすべて.all()の出現を削除できます。マネージャー(.objects)にはすでに.delete()を除くQuerySetのほぼすべてのメソッドがあります。

.select_relatedは、最終的なクエリがモデルインスタンスを返す場合にのみ役に立ちます。各インスタンスのすべての外部キーがプリロードされます。

ただし、.valuesを使用している場合は、辞書が取得されており、事前ロードする外部キー属性はありません。その場合は使用しないでください。

.values('owner__name') Djangoは所有者と車に参加する必要があると既に見ているため、追加のクエリは実行されません。あなたが国にしたいので、Country.objectsを使用する最後のもので

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

フィードバックいただきありがとうございます。しかし、djangoは各要素を反復すると想像することもできますが、Djangoはデータベース内で新しい結合クエリを作成できます。これは、私がこの場合有用でないselect関連が確実であることを確認したい理由です。 – srjjio