如果我为查询集执行prefetch_related('toppings')
,并且我希望稍后filter(spicy=True)
通过相关表中的字段,Django会忽略缓存的信息并执行数据库查询。我发现这是documented(在注释框下),并且当执行另一个select_related()
时,似乎会发生所有形式的缓存(filter()
,已经评估过的查询集等)。 / p>
但是,是否存在某种超级秘密隐藏节省时间的快捷方式,可以在本地过滤(使用缓存而不是访问数据库),而无需编写python代码来循环查询集(使用list / dict理解等)。 )?也许像filter_locally(spicy=True)
?
修改
列表/理解对我不适用的原因之一是因为list / dict没有queryset方法。在我的情况下,第一级M2M字段toppings
不是我的最终目标,我需要检查第二个相关的M2M字段(我已经预先获取)。虽然使用列表理解也可以做到这一点,但是拥有诸如filter_locally(spicy=True, origin__country='Spain')
之类的东西要简单得多,因为:
filter()
filter()
修改现有代码更容易,无需预取即可添加此优化而无需进行太多更改。但是从回答来看,Django没有这样的支持:(
答案 0 :(得分:3)
你必须编写python代码来遍历查询集(列表/字典理解是理想的)。所有filter()
代码都知道如何为发送到数据库的SQL添加过滤语言。本地过滤与远程过滤完全不同,因此这两个独立问题的解决方案将无法共享任何逻辑。
但是,列表理解单行是非常简单的;语法可能没有filter()
复杂得多。
答案 1 :(得分:1)
如果你正在过滤布尔值,那么列表理解就很容易了。您也可以换出topping.spicy==True
进行字符串比较或其他。
我会做类似的事情:
qs = Pizza.objects.all().prefetch_related('toppings')
res = list(qs)
def get_spicy(qs):
res = list(qs)
return [pizza for pizza in res if any(topping.spicy==True for
topping in pizza.toppings.all())]
如果您想要返回披萨对象,如果任何的配料是辣的话。您还可以将all()替换为all()以检查所有内容,并使用此语法执行许多非常强大的查询。我有点惊讶在django中没有简单的方法可以做到这一点。似乎很多这些简单的查询应该易于以通用方式实现。
上面的代码假设有很多。应该很容易修改以使用简单的FK关系,例如one2one或one2many。
希望这有用。