gpt4 book ai didi

python - 带有使用管理器方法的自定义查询集的 Django Prefetch

转载 作者:太空狗 更新时间:2023-10-29 21:48:51 25 4
gpt4 key购买 nike

让我们看一下 django 文档中的披萨和浇头模型示例。一个披萨可能有多种配料。

如果我们进行查询:

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))

现在让我们假设我们有一个 Topping 模型的自定义管理器,我们决定在那里放一个方法,让我们像上面的代码示例一样只过滤素食浇头:

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)

最佳答案

我没有直接测试过,但是你不应该在循环中再次调用方法或过滤器,因为 prefetch_related 已经附加了数据。所以这些中的任何一个都应该工作:

pizzas = Pizza.objects.prefetch_related(
Prefetch('toppings', queryset=Topping.objects.filter(is_vegetarian=True))
)
for pizza in pizzas:
print(pizza.toppings.all()) # uses prefetched queryset

pizzas = Pizza.objects.prefetch_related(
Prefetch('toppings', queryset=Topping.objects.filter_vegetarian(),
to_attr="veg_toppings"))
for pizza in pizzas:
print(pizza.toppings.veg_toppings)

您的示例不起作用,因为它们调用了另一个查询集,并且无法将其与预取的查询集进行比较以确定它是否相同。

它也这么说in the docs :

The prefetch_related('toppings') implied pizza.toppings.all(), but pizza.toppings.filter() is a new and different query. The prefetched cache can’t help here; in fact it hurts performance, since you have done a database query that you haven’t used.

Using to_attr is recommended when filtering down the prefetch result as it is less ambiguous than storing a filtered result in the related manager’s cache.

关于python - 带有使用管理器方法的自定义查询集的 Django Prefetch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38487303/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com