2012-12-20 12 views
28

がsimplcityのためにDjangoのモデルとしてこれらを仮定:djangoでは、プリフェッチ関連のモデルで関連するフィールドを選択できますか?

class A(): 

    a = manytomany('B') 

class B(): 

    b = charfield() 
    z = foreignkey('C') 

class C(): 

    c = charfield() 

我々はまた、zを取得するために、このような何かを行うことができます。

foo = A.objects.get(pk = 1).prefetch_related('a').select_related('a__z') 
+0

これはすべてマニュアルの... https://docs.djangoproject.com/en/dev/ref/models/querysets/でカバーされていますが、「はい」が答えです。 – demux

+1

実際、答えは "no"です。質問に書かれているような 'select_related'呼び出しはうまくいきません。新しい回答を追加します。ちなみに、 'get'コールは' select_related'と 'prefetch_related'の前ではなく最後にあるべきです。 – koniiiik

答えて

21

は1つのだけですprefetch_relatedコールが必要です。

foo = A.objects.prefetch_related('a__z').get(pk=1) 

これにより、両方のテーブルがプリフェッチされます。 Django 1.7+ではkoniiiik's answerのようにPrefetchオブジェクトを使ってパフォーマンスを向上させることができます。

+1

プリフェッチ関連は 'manytomanyfield'だけで動作すると思っていましたが、' foreignkey'でも使えますか? –

+0

Arnarはコメントの中で、これは[prefetch関連のドキュメント](https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related)でカバーされています。あなたのユースケースは、例>>>> Restaurant.objects.prefetch_related( 'best_pizza__toppings') 'に似ています。 – Alasdair

+0

これがうまくいかない状況はありますか?私は、モデルaにbの外部キーとcの外部キーがあるという問題があります。私はc.objects.prefetch_related( 'a__b')をしたいが、それはaのセットを取り出して、bのために何もしない。 – Adam

39

This answerは、1.7より前のDjangoのバージョンでは正しいです。最初に、Aのインスタンスをフェッチし、次に関連するインスタンスBをフェッチし、最後にBのインスタンスに関連するCのインスタンスを2番目のクエリでフェッチします。

ジャンゴ1.7前に、これは2番目のクエリは、理論的には、zForeignKey介して結合し、関連Cオブジェクトと一緒にすべてのBのオブジェクトを選択することができていても、あなたができる最善です。

Django 1.7からは、より高度なdjango.db.models.Prefetchクラスがあります。このクラスでは、これを行うことができます。 Prefetchを使用すると、このように関連するオブジェクトをプリフェッチするために使用するクエリセットをカスタマイズすることができます。

foo = A.objects.prefetch_related(
    Prefetch('a', queryset=B.objects.select_related('z')) 
).get(pk=1) 

これが唯一の2つのクエリになり(prefetch_related('a__z')を使用するときに3とは反対に)、データベースが参加する第二の世話をすることができます、はず理論的にはパフォーマンスがやや向上します。

+4

これはすばらしいです!私はPrefetchについて知らなかった。ありがとう。将来使用する人のための注意: 'Prefetch'はモデルインポート空間にありますので、例のようにインポートするには' django.db.models import prefetch' –

+1

良い点、インポートを追加しました。答えへのパスと、ドキュメントへのリンクが含まれています。提案していただきありがとうございます。 – koniiiik

関連する問題