Ленивая оценка в генераторе с Django модельными объектами - PullRequest
0 голосов
/ 10 февраля 2020

Я пытаюсь понять, как использовать Django QuerySet в генераторе Python, чтобы он выполнял ленивые вычисления.

В документации явно не упоминаются генераторы, это кажется единственным (более или менее) связанным замечанием, но оно не проясняет мой вопрос:

Вы можете оценить QuerySet следующими способами:

  • итерация. QuerySet является итеративным и выполняет свой запрос к базе данных при первой итерации по нему.

  • [...]

У меня есть 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())

1 Ответ

0 голосов
/ 10 февраля 2020

Похоже, что выражение генератора действительно учитывает «итерацию», в результате чего Django получает все документы из QuerySet из базы данных. Чтобы решить эту проблему, используйте метод iterator():

(doc.process for doc in Document.objects.iterator())
...