在将其他过滤器应用于查询集时,Django会使用先前评估的结果吗?

时间:2017-01-25 19:48:44

标签: django django-orm

让我们说我需要在一组模型对象上做一些工作,以及第一组的子集:

things = Thing.objects.filter(active=True)
for thing in things:                # (1)
    pass # do something with each `thing`

special_things = things.filter(special=True)
for thing in special_things:        # (2)
    pass # do something more with these things

我的理解是,在上面代码中标记的第(1)点,将对数据库执行类似SELECT * FROM things_table WHERE active=1的实际SQL查询。 QuerySet documentation也说:

  

评估QuerySet时,它通常会缓存其结果。

现在我的问题是,上面示例Python代码中的第(2)点会发生什么?

Django会执行第二个SQL查询,例如SELECT * FROM things_table WHERE active=1 AND special=1吗?

或者,它是否会使用之前的缓存结果,在幕后自动为我做更优化的filter(lambda d: d.special == True, things),即避免不必要的第二次数据库访问?

无论哪种方式,当前的行为是保证的(通过文档或其他东西)还是我不应该依赖它?例如,它不仅是一个优化点,而且如果数据库表被两个潜在查询之间的另一个线程/进程修改,也可能产生逻辑差异。

1 个答案:

答案 0 :(得分:1)

它将执行第二个SQL查询。 filter创建一个新的查询集,该查询集不会复制结果缓存。

至于保证 - 嗯,文档指定filter返回一个新的queryset对象。我认为您可以确信新的查询集还没有缓存结果。作为进一步的支持,"什么时候评估查询集"如果您想要获取可能更改的结果,docs建议使用.all()来获取新的查询集:

  

如果自QuerySet以来数据库中的数据可能已更改   通过调用,您可以获得相同查询的更新结果   在先前评估的QuerySet上的all()。