Оптимизировать запрос для итерации в шаблоне - PullRequest
0 голосов
/ 30 января 2020

Я создаю приложение, в котором перечислены эпизоды и категории для подкаста. Отношения модели устанавливаются таким образом

models.py

class Podcast(models.Model):
    ...

    @property
    def episodes_by_category(self):
        category_list = []
        for category in self.category_set.all():
            category_list.append({
                'category': category,
                'episodes': self.episode_set.all().filter(categories=category),
                'count': self.episode_set.all().filter(categories=category).count(),
            })
        return sorted(category_list, key = lambda i: i['count'],reverse=True)


class Category(models.Model):
    ...
    podcast = models.ForeignKey(Podcast, on_delete=models.CASCADE)
    ...

    def get_absolute_url(self):
        kwargs = {
            'slug': self.podcast.slug,
            'category_slug': self.slug
        }
        return reverse('category_page', kwargs=kwargs)

class Episode(models.Model):
    ...
    podcast = models.ForeignKey(Podcast, on_delete=models.CASCADE)
    categories = models.ManyToManyField(Category)
    ...

    def get_absolute_url(self):
        kwargs = {
            'show_slug': self.podcast.slug,    
            'pk': self.id,
            'slug': self.slug
        }
        return reverse('episode_page', kwargs=kwargs)

На странице подкаста я использую episodes_by_category, чтобы показать список категорий, каждая с несколькими эпизодами

В DetailView Это вызывает значительное количество запросов к базе данных. Вот как это происходит:

views.py

class PodcastPage(DetailView):
    model = Podcast
    template_name = 'dashboard/public/podcast_page.html'

    def get_context_data(self, **kwargs):
        context = super(PodcastPage, self).get_context_data(**kwargs)
        context['episodes'] = self.get_object().get_episodes[:10].prefetch_related('categories')
        return context

podcast_page. html

{% for episode_batch in podcast.episodes_by_category %}
    <div class="sidebar-object">
        <div class="section-title section-title--style-1 mb-0">
            <h3 class="section-title-inner heading-sm strong-600 text-uppercase">
                Top <a href="{{episode_batch.category.get_absolute_url}}" class="link">{{episode_batch.category.name|title}}</a> Episodes
            </h3>
        </div>

        <ul class="categories list-border--dotted">
            {% for episode in episode_batch.episodes %}
                {% if forloop.counter < 4 %}
                    <li>
                        <a href="{{episode.get_absolute_url}}">{{episode.name}}</a>
                    </li>
                {% endif %}
            {% endfor %}
        </ul>
    </div>
{% endfor %}

Что я могу оптимизировать в этом логике c, чтобы сделать его более эффективнее и меньше попадать в базу?

1 Ответ

0 голосов
/ 30 января 2020

Этот лог c мне кажется вполне подходящим, вам, вероятно, просто нужна некоторая оптимизация в ваших запросах

Вы должны установить Django панель инструментов отладки

https://django-debug-toolbar.readthedocs.io/en/latest/installation.html

Это позволит вам увидеть, сколько запросов отправляется в базу данных при каждом просмотре, а затем оптимизировать его

. Вам также следует обратить внимание на select_related() и prefetch_related(). Это полезно, когда речь заходит об оптимизации запросов. Они позволяют вам сделать только один большой запрос вместо множества маленьких

https://docs.djangoproject.com/fr/3.0/ref/models/querysets/#select связанных https://docs.djangoproject.com/fr/3.0/ref/models/querysets/#prefetch связанных

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...