使用 Django 模型对象在生成器中进行延迟评估
Lazy evaluation in generator with Django model objects
我正在尝试了解如何在 Python 生成器中使用 Django QuerySet 以便它延迟计算。
文档没有明确提到生成器,这似乎是唯一(或多或少)相关的评论,但它没有澄清我的问题:
You can evaluate a QuerySet in the following ways:
Iteration. A QuerySet is iterable, and it executes its database query the first time you iterate over it.
[...]
我有一个像这样的 Django 模型:
class Document(models.Model):
text = [...]
@cached_property
def process(self):
[...]
现在我试试这个:
processed = (doc.process for doc in Document.objects.all())
但是,我注意到,这会立即为所有对象触发 process()
方法,从而导致内存消耗激增。
逐步调查:
docs = Document.objects.all()
test = (doc for doc in docs)
Document.objects.all()
不会触发任何计算,它只会按预期创建 QuerySet
。
但是,第二行 (test
) 已经将整个文档集加载到内存中,因此上面显示的 process()
调用显然不是问题。
在我看来,从 QuerySet 创建生成器理解已经触发了 Django 数据库调用。如果是这样的话,我怎样才能正确地实现我最初想要的,即像这样延迟评估的生成器:
(doc.process for doc in Document.objects.all())
看起来生成器表达式确实说明了 'iteration',导致 Django 从数据库中检索 QuerySet 中的所有文档。要解决此问题,请使用 iterator()
方法:
(doc.process for doc in Document.objects.iterator())
我正在尝试了解如何在 Python 生成器中使用 Django QuerySet 以便它延迟计算。
文档没有明确提到生成器,这似乎是唯一(或多或少)相关的评论,但它没有澄清我的问题:
You can evaluate a QuerySet in the following ways:
Iteration. A QuerySet is iterable, and it executes its database query the first time you iterate over it.
[...]
我有一个像这样的 Django 模型:
class Document(models.Model):
text = [...]
@cached_property
def process(self):
[...]
现在我试试这个:
processed = (doc.process for doc in Document.objects.all())
但是,我注意到,这会立即为所有对象触发 process()
方法,从而导致内存消耗激增。
逐步调查:
docs = Document.objects.all()
test = (doc for doc in docs)
Document.objects.all()
不会触发任何计算,它只会按预期创建 QuerySet
。
但是,第二行 (test
) 已经将整个文档集加载到内存中,因此上面显示的 process()
调用显然不是问题。
在我看来,从 QuerySet 创建生成器理解已经触发了 Django 数据库调用。如果是这样的话,我怎样才能正确地实现我最初想要的,即像这样延迟评估的生成器:
(doc.process for doc in Document.objects.all())
看起来生成器表达式确实说明了 'iteration',导致 Django 从数据库中检索 QuerySet 中的所有文档。要解决此问题,请使用 iterator()
方法:
(doc.process for doc in Document.objects.iterator())