假设我需要对一组模型对象以及第一组的子集做一些工作:
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文档还说:
当计算一个QuerySet时,它通常缓存其结果。
现在我的问题是,在上面的Python代码示例中,在(2)点发生了什么?
将执行第二个SQL查询,类似于SELECT * FROM things_table WHERE active=1 AND special=1。
或者,它是否会使用前面缓存的结果,自动地在幕后为我做一些类似于最优的filter(lambda d: d.special == True, things),即避免不必要的第二次访问数据库?
无论哪种方式,当前的行为(通过文档或其他方式)是得到保证的,还是我不应该依赖它?例如,它不仅是一个优化点,而且如果数据库表被两个潜在查询之间的另一个线程/进程修改,则可能会产生逻辑差异。
发布于 2017-01-25 19:55:45
它将执行第二个SQL查询。filter创建一个新的查询集,它不复制结果缓存。
至于保证,文档指定filter返回一个新的queryset对象。我认为您可以相信新的queryset不会有缓存的结果。作为进一步的支持,“何时进行查询集评估”文档建议使用.all()获取一个新的查询集,如果您想获取可能更改的结果:
如果数据库中的数据可能在计算QuerySet后发生了变化,则可以通过调用以前计算过的QuerySet上的all()来获得相同查询的更新结果。
https://stackoverflow.com/questions/41860384
复制相似问题