Оптимизация аналогичных кверисетов в Django

Я создаю сайт с фильмографией. Однако мне трудно оптимизировать набор запросов в детальном просмотре.

class Actor(model.Models):
    id = models.IntegerField()
    name = models.CharField()

class Movie(model.Models):
    id = models.IntegerField()
    movie_title = models.CharField()
    actor = models.ManyToManyField(Actor, related_name='relations')

class ActorView(DetailView):
    model = Actor
    context_object_name = 'actor'
    template_name = 'actor.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['movies'] = self.object.relations.all()
        return context


<div>
   {{ actor.name }}
   {% for movie in movies %}
       {{ movie.movie_title }}
       {% for actor_info in movie.actor.all %}
       {{ actor.name }}
       {% endfor %}
   {% endfor %}
</div>

Я проверил sql-тап в отладочной консоли django.

   {% for actor_info in movie.actor.all %}
   {{ actor.name }}
   {% endfor %}

В приведенном выше коде похожие запросы выполняются многократно. И время соединения с данными и выполнения запроса также очень медленное. Как я могу оптимизировать эту часть в представлении или модели?

Вы можете ускорить этот процесс, используя prefetch_related

Так что в вашем представлении измените эту строку на

context['movies'] = self.object.relations.all()

to

context['movies'] = self.object.relations.all().prefetch_related("actor")

В Django, select_related и prefetch_related предназначены для того, чтобы остановить поток запросов к базе данных, вызванных обращением к связанным объектам, как упоминалось

Итак, для отношений ForeignKey и OneToOneField можно использовать select_related, а для отношений ManyToManyField можно использовать prefetch_related, которые.

Django говорит

Prefetch related возвращает QuerySet, который автоматически извлекает, в одном пакете, связанные объекты для каждого из указанных поисков.

Это имеет сходное назначение с select_related, в том смысле, что оба предназначены для прекращения потока запросов к базе данных, вызванного обращением к связанным объектам, но стратегия совершенно другая.

select_related работает путем создания SQL-соединения и включения полей связанного объекта в оператор SELECT. По этой причине select_related получает связанные объекты в одном запросе к базе данных. Однако, чтобы избежать гораздо большего набора результатов, который может возникнуть в результате объединения через "многие" отношения, select_related ограничен однозначными отношениями - внешним ключом и один-к-одному.

.

class ActorView(DetailView):
    model = Actor
    context_object_name = 'actor'
    template_name = 'actor.html'

    # Overide the get_object method and set prefetch_related
    def get_object(self, queryset):
        return super().get_object(queryset).prefetch_related("movies")

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['movies'] = self.get_object().relations.all()
        return context

Вернуться на верх