モデルが次のようになっている場合:
_class Publisher(models.Model):
pass
class Book(models.Model):
publisher = models.ForeignKey(Publisher)
class Page(models.Model):
book = models.ForeignKey(Book)
_
Publisher
のクエリセットを取得したいのですが、Publisher.object.all()
を実行します。その後、プリフェッチを確実にしたい場合は、次のことができます:
_Publisher.objects.all().prefetch_related('book_set')`
_
私の質問は:
select_related
_を使用してこのプリフェッチを行う方法はありますか、または_prefetch_related
_を使用する必要がありますか?page_set
_をプリフェッチする方法はありますか?これは動作しません:Publisher.objects.all().prefetch_related('book_set', 'book_set_page_set')
いいえ、逆関係に_select_related
_を使用することはできません。 _select_related
_はSQL結合を行うため、メインクエリセットの単一レコードは、関連テーブル(ForeignKey
またはOneToOne
フィールド)の1つを正確に参照する必要があります。 _prefetch_related
_は、実際には完全に別の2番目のクエリを実行し、結果をキャッシュしてから、それをPythonのクエリセットに「結合」します。そのため、ManyToMany
または逆ForeignKey
フィールドに必要です。
マルチレベルのプリフェッチを行うために2つのアンダースコアを試しましたか?このように:Publisher.objects.all().prefetch_related('book_set', 'book_set__page_set')
Django 1.7なので、Django.db.models.Prefetch
クラスのインスタンスは.prefetch_related
の引数として使用できます。Prefetch
オブジェクトコンストラクタにはqueryset
そのようにネストされた複数レベルのプリフェッチを指定できるようにする引数:
Project.objects.filter(
is_main_section=True
).select_related(
'project_group'
).prefetch_related(
Prefetch(
'project_group__project_set',
queryset=Project.objects.prefetch_related(
Prefetch(
'projectmember_set',
to_attr='projectmember_list'
)
),
to_attr='project_list'
)
)
ListQuerySet
を使用してプリフェッチ結果を処理するため(フィルター/順序)、サフィックスが_list
の属性に格納されます。