#python #django #wagtail
#python #django #wagtail
Вопрос:
Проблема, с которой я сталкиваюсь, заключается в повторяющемся количестве запросов, что замедляет работу приложения при использовании get_parent () или get_children () в модели страницы. которые также увеличиваются, если на родительской странице есть файл изображения, который используется в шаблоне.
итак, я ищу способ предварительной выборки связанных страниц без создания отношения foriegn key.
допустим, у меня есть модель страницы TVSeries и модель страницы Episode:
class TvSeries(Page):
name = models.CharField()
producer = models.CharField()
subpage_types = ['Episode']
class Episode(Page):
title = models.CharField()
number = models.CharField()
parent_page_types = ['TvSeries']
Необходимо выполнять предварительную выборку TVSeries при запросе модели эпизода! Как уменьшить количество вызовов базы данных? Возможно ли использовать предварительную выборку и выбирать связанные? если да, то как?. и если нет, то каково решение проблемы увеличения количества запросов?
Комментарии:
1. Это только расширяет одну модель
Page
и не имеет никаких особых различий междуTvSeries
иEpisode
? Можете ли вы показать модельPage
2. Я использую Wagtail CMS. Наследование модели страницы, которая наследуется от Django-treebeard
Ответ №1:
prefetch_related
не может использоваться для отношений родительской / дочерней страниц, поскольку они не используют стандартное ForeignKey
отношение Django — вместо этого Wagtail (и Treebeard) использует path
поле для представления положения в дереве. Это позволяет выполнять запросы, которые невозможно эффективно выполнить с ForeignKey
, такие как выборка всех потомков (на любой глубине) страницы.
Следует отметить, что prefetch_related
это не «бесплатно» — это сгенерирует один дополнительный запрос для каждого последующего отношения. Методы запроса Treebeard обычно равны или лучше этого по эффективности — например:
series = TvSeries.objects.get(id=123)
episodes = series.get_children()
будет извлекать TvSeries
и все его эпизоды в двух запросах, точно так же, как (гипотетическое) prefetch_related
выражение:
# fake code, will not work...
series = TvSeries.objects.filter(id=123).prefetch_related('child_pages')
Однако одна из проблем get_children
заключается в том, что он будет возвращать только базовые Page
экземпляры, поэтому для извлечения определенных полей из Episode
требуются дополнительные запросы. Вы можете избежать этого, используя child_of
вместо:
series = TvSeries.objects.get(id=123)
episodes = Episode.objects.child_of(series)
Комментарии:
1. Проблема в том, что у вас есть несколько объектов. Допустим, мы хотим получить последние 30 эпизодов с их родителями: latest_episodes = Episode.objects.all()[:30] >>> теперь вам нужно будет выполнить get_parent() или parent_of() для каждого эпизода. это вызов на 30 дб, добавьте к этому, если у родительского файла есть файл изображения, тогда у вас будет вызов еще на 30 дб. Я начинаю думать, что лучшим решением является создание родительского ключа или написание моего собственного необработанного запроса. Спасибо
2. Я тоже борюсь с этим
3. Это правда, что древовидная структура допускает некоторые изящные вещи, но нам гораздо чаще нужен простой родительский поиск…
prefetch_related
не является «бесплатным», ноselect_related
переводится на стандартныеJOIN
языки — поскольку каждая страница может иметь только 1 прямого родителя, меня также расстраивает, что дочерняя страница не может получить своего родителя одним запросом. я думаю, мы также добавим идентификатор родительского указателя или что-то подобное…