Django:从缓存本地过滤查询集

时间:2013-11-04 20:09:26

标签: django django-models

如果我为查询集执行prefetch_related('toppings'),并且我希望稍后filter(spicy=True)通过相关表中的字段,Django会忽略缓存的信息并执行数据库查询。我发现这是documented(在注释框下),并且当执行另一个select_related()时,似乎会发生所有形式的缓存(filter(),已经评估过的查询集等)。 / p>

但是,是否存在某种超级秘密隐藏节省时间的快捷方式,可以在本地过滤(使用缓存而不是访问数据库),而无需编写python代码来循环查询集(使用list / dict理解等)。 )?也许像filter_locally(spicy=True)

修改

列表/理解对我不适用的原因之一是因为l​​ist / dict没有queryset方法。在我的情况下,第一级M2M字段toppings不是我的最终目标,我需要检查第二个相关的M2M字段(我已经预先获取)。虽然使用列表理解也可以做到这一点,但是拥有诸如filter_locally(spicy=True, origin__country='Spain')之类的东西要简单得多,因为:

  1. 它允许轻松访问多个级别的相关字段
  2. 它允许链接其他查询集方法
  3. 它更容易阅读,因为它与熟悉的filter()
  4. 一致
  5. 使用filter()修改现有代码更容易,无需预取即可添加此优化而无需进行太多更改。
  6. 但是从回答来看,Django没有这样的支持:(

2 个答案:

答案 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。

希望这有用。