Django Запрос количества вложенных объектов ManyToManyField - PullRequest
0 голосов
/ 07 января 2020
  • у нас есть Project в качестве основной модели, которая содержит 2 поля отношения M2M.
class First(models.Model):
   first_results_M2M = models.ManyToManyField(First_Results)

class Second(models.Model):
   second_results_M2M = models.ManyToManyField(Second_Results)

class Project(models.Model):
    project_first_M2M = models.ManyToManyField(First)
    project_second_M2M = models.ManyToManyField(Second)
  • Я пытаюсь сосчитать все присутствующие объекты в first_results_M2M всех project_first_M2M объектов внутри каждого Project объекта.

  • Ниже приведен пример подсчета всех объектов first_results_M2M для Project объекта 1.

total_first_all = First_Results.objects.filter(first__project__id=1).count()

  • Я хочу отобразить общее количество total_first_all и total_second_all в шаблоне.
Project_Query = Project.objects.all()
for each_proj in Project_Query:
  print(each_proj.total_first_all) ## should print the count the `first_resuls_M2M` for each project obj.
  • Пожалуйста, дайте мне знать, как добиться этого более эффективным / быстрым способом, кроме аннотирования.

annotate.total_first_all=Count('project_first_M2M__first_results_M2M')

1 Ответ

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

Вы .annotate(..) [Django -doc] ваш набор запросов, например:

from django.db.models import Count

project_query = Project.objects.annotate(
    <b>total_first_all=Count('project_first_M2M__first_results_M2M')</b>
)

for project in project_query:
    print(project.total_first_all)

Это будет не сделать запрос на Project объекта, но вычислите счетчики для всех Project с "навалом".

Для нескольких объектов вы можете использовать подзапросы для уменьшения количества вложенных JOIN:

from django.db.models import Count, OuterRef, Subquery

project_query = Project.objects.annotate(
    total_first_all=Subquery(
        <b>First_Results.objects.filter(first__project=OuterRef('pk')).values('first__project').values(cnt=Count('*')).order_by('first__project')</b>
    ),
    total_second_all=Subquery(
        <b>Second_Results.objects.filter(second__project=OuterRef('pk')).values('second__project').values(cnt=Count('*')).order_by('second__project')</b>
    )
)
...