问题 在django queryset上使用iterator()


我最近遇到了一些奇怪的行为,需要检查一下我的理解。

我在模型中使用了一个简单的过滤器,然后迭代结果。

例如

allbooks = Book.objects.filter(author = 'A.A. Milne')

for book in allbooks:
   do_something(book)

奇怪的是,它只返回了部分书籍清单。

但是,当使用相同的代码并使用iterator()时,这似乎运行良好。

for book in allbooks.iterator():
    do_something(book)

知道为什么??

附:我确实浏览了django文档,但看不出qeuryset如何在其他任何地方缓存...

iterator()   计算QuerySet(通过执行查询)并在结果上返回一个迭代器。 QuerySet通常在内部缓存其结果,以便重复的评估不会导致其他查询; iterator() 而是直接读取结果,而不在QuerySet级别进行任何缓存。对于返回大量对象的QuerySet,这通常会带来更好的性能并显着降低内存

注意使用 iterator() 在已经评估的QuerySet上将强制它再次评估,重复查询。


4779
2018-02-20 18:02


起源

我刚注意到的另一件奇怪的事不使用iterator()时 - 它只返回100个对象。这似乎与前100个对象由'自动缓存的事实相匹配'ITER',但我仍然想知道为什么循环只是在那里结束,并且不会继续迭代匹配过滤器的所有对象。 - gingerlime


答案:


奇怪的是,它只返回了一部分   书籍清单。

这不是查询集必须如何工作。迭代查询集应该为您提供数据库返回的每条记录。调试你的代码。你会发现错误,否则再次调试。

在REPL中检查很容易。跑 manage.py shell

from app.models import Model
for o in Model.objects.filter(fieldname="foo"): print o

#Let's see DB query
from django.db import connection
print connection.queries

15
2018-02-20 22:20



谢谢,完全相同的代码与没有.iterator()的相同数据库返回100条记录。有了它--129。另外,如果我这样做:len(allbooks)for book中的书:返回129 - gingerlime
你是对的。 do_something(书)里面的东西正在迭代同样的allbooks ... doh! - gingerlime


QuerySet通常在内部缓存其结果,以便重复的计算不会导致其他查询。相反, iterator() 将直接读取结果,而不进行任何缓存 QuerySet 水平。

https://docs.djangoproject.com/en/dev/ref/models/querysets/


0
2017-08-18 14:11