PizzaとToppingモデルのdjangoドキュメントの例を見てみましょう。 1つのピザは複数のトッピングを持つことがあります。Django Prefetchでマネージャメソッドを使用するカスタムクエリセット
pizzas = Pizza.objects.prefetch_related('toppings')
我々は2つのクエリーですべてのピザとそれらのトッピングを得るでしょう:私たちは、クエリを作成する場合は
。 は今、(私たちは、このような性質を持っていると仮定)のは、私が唯一のベジタリアントッピングをプリフェッチしたいとしましょう:
pizzas = Pizza.objects.prefetch_related(
Prefetch('toppings', queryset=Topping.objects.filter(is_vegetarian=True))
)
それはかなりうまく機能し、このようなものを作るときDjangoは、それぞれのピザのためのさらに別のクエリを実行しません。
for pizza in pizzas:
print(pizza.toppings.filter(is_vegetarian=True))
今度は私たちがモデルをトッピング用のカスタムマネージャを持っていると仮定しましょう、私たちはそこに私たちは、上記のコード例のように唯一のベジタリアントッピングをフィルタリングすることを可能にする方法置くことにしました:
class ToppingManager(models.Manager):
def filter_vegetarian(self):
return self.filter(is_vegetarian=True)
を
今私は、管理者からの私の方法を使用して新しいクエリとプリフェッチカスタムクエリセットを作る:
pizzas = Pizza.objects.prefetch_related(
Prefetch('toppings', queryset=Topping.objects.filter_vegetarian()))
そして、私のコードを実行しよう:
for pizza in pizzas:
print(pizza.toppings.filter_vegeterian())
私は反復ごとに新しいもののクエリを取得ループの それは私の質問です。どうして? これらの構造はどちらもクエリセットで同じ型のオブジェクトを返す:私はこれを直接テストしていない
Topping.objects.filter_vegetarian()
Topping.objects.filter(is_vegetarian=True)
マネージャメソッドを使用してプリフェッチを行いますが、forループでプリフェッチを実行すると(pizza.toppings.filter(is_vegetarian = True))、追加のクエリが作成されますか?私はなぜこれが起こっているのか理解していると感じています。ただ、それが想像するように動作することを確認したいだけです。 –
私はそれをデバッグし始めました、そして、最初の例でさえ、我々はあまりにも多くのクエリを持っているようです。それで、docsが私たちを使うことを勧めているのはto_attr –
しかしそれはまだ興味深いです。なぜこの機能をdjangoに実装しないのですか?プリフェッチされたクエリーセットが、キャッシュされた結果を引き続き使用できるようになった後にフィルタリングされたものと同じ場合 –