Требуется оптимизация запросов Django (2 запроса вместо 21)
У меня есть проект Django на EBS, и один метод, который возвращает QuerySet из Article объектов, занимает довольно много времени. Я бы хотел оптимизировать его так, чтобы это был всего один или два запроса, но я не уверен, что это вообще возможно.
Модели: WebSite,Article
Запрос представляет собой список Articles с различных сайтов.
WebSite модель имеет атрибуты home_order и home_article_count, которые используются для выбора количества статей и того, в каком порядке они находятся.
Пример для сайтов A, B и C:
A-A.home_order = 2,A.home_article_count=3B-B.home_order = 1,B.home_article_count=5C-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)))
В итоге у вас должно быть всего два запроса: один для получения сайтов и один для создания и использования списка статей.