Требуется оптимизация запросов Django (2 запроса вместо 21)

У меня есть проект Django на EBS, и один метод, который возвращает QuerySet из Article объектов, занимает довольно много времени. Я бы хотел оптимизировать его так, чтобы это был всего один или два запроса, но я не уверен, что это вообще возможно.

Модели: WebSite,Article

Запрос представляет собой список Articles с различных сайтов.

WebSite модель имеет атрибуты home_order и home_article_count, которые используются для выбора количества статей и того, в каком порядке они находятся.

Пример для сайтов A, B и C:

  1. A - A.home_order = 2, A.home_article_count=3
  2. B - B.home_order = 1, B.home_article_count=5
  3. C - C.home_order = 3, C.home_article_count=7

Результатом будет (aA означает статью с сайта A):

aB,aB,aB,aB,aB,aA,aA,aA,aC,aC,aC,aC,aC,aC,aC,aC

Списки начинаются с aB, что означает статьи с сайта B, потому что B.home_order=1, есть 5 aB статей как B.home_article_count=5.

Сейчас это метод Manager, который возвращает статьи:

def home(self) -> QuerySet:
    articles_pks = []
    for ws in WebSite.objects.active().order_by('home_order', 'name'):
        articles_pks.extend(ws.articles.filter(is_active=True).order_by('-created')[:ws.home_article_count].values_list('pk',flat=True))
    return self.get_queryset().filter(pk__in=articles_pks)

Значит, на 20 объектов WebSite приходится 21 запрос (один, который получает сайты, а другие 20 для статей).

Можно ли объединить его в один или два запроса, соблюдая WebSite.home_order и WebSite.home_article_count?

Попробуйте объединить наборы запросов с помощью оператора OR |:

def home(self) -> QuerySet:
    articles_pks = Article.objects.none()
    for ws in WebSite.objects.active().order_by('home_order', 'name'):
        articles_pks = articles_pks | ws.articles.filter(is_active=True).order_by('-created')[:ws.home_article_count]
    return self.get_queryset().filter(pk__in=articles_pks.values_list('pk',flat=True)))

В итоге у вас должно быть всего два запроса: один для получения сайтов и один для создания и использования списка статей.

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