Какие легкие опции кэширования 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