Какие легкие опции кэширования django существуют для простого внутреннего цикла в одном сеансе?

У меня есть что-то похожее на это:

pages = Page.objects.prefetch_related("sections","sections__tiles").all()
for page in pages:
    for section in page.sections.all():
        for tile in section.tiles.all():
            print tile.author
            # more stuff to build each page

Это поражает уровень SQL один раз для начального запроса, затем один раз за цикл (n+1). Однако оптимальное количество SQL-запросов - 1 + (количество уникальных авторов).

Я реализовал простой хеш-код на основе "авторов" и значительно сократил время загрузки.

cache_author = {}
def author_cache(author_id):
    author = cache_author.get(author_id, None)
    if author:
        return author
    else:
        author = Author.objects.get(id=author_id)
        cache_author[author_id] = author
        return author

pages = Page.objects.prefetch_related("sections","sections__tiles").all()
for page in pages:
    for section in page.sections.all():
        for tile in section.tiles.all():
            print author_cache(tile.author_id)
            # more stuff to build each page

Но это кажется грязным. Какие есть более чистые варианты для сокращения накладных расходов на SQL внутри одной транзакции?

1 ответ

Опять же, я не могу быть уверенным, не видя моделей, но я протестировал эту настройку в Django 1.7, и она должна получить все только с помощью пары запросов.

pages = Page.objects.prefetch_related("sections","sections__tiles").all().select_related(‌​'sections__tiles__author')
for page in pages:
for section in page.sections.all():
    for tile in section.tiles.all():
        print tile.author
Другие вопросы по тегам