Подсчет детей, удовлетворяющих условиям внуков, в одном запросе Django

Учитывая следующие модели:

class Flight:

class Checklist:
    flight = ForeignKey(Flight)

class Item:
    checklist = ForeignKey(Checklist)
    completed = BooleanField()

Мне нужно получить количество заполненных контрольных листов для каждого рейса. Контрольный список считается завершенным, если все его пункты выполнены.

Я знаю, что для контрольных списков я могу сделать

Checklist.objects.annotate(
    is_complete=~Exists(Item.objects.filter(
        completed=False, 
        checklist_id=OuterRef('pk'),
    ))
)

но мне нужно что-то для полетов, в идеале один запрос. Что-то вроде

Flight.objects.annotate(
    completed_checklists=Count(
        Checklist.objects.annotate(<is complete annotation here>).filter(is_complete=True)
    )
)

Вы можете добавить в модели функцию, подобную следующей:

    def get_total(self):
        #start with a zero total
        total = 0
        #check for all the checklist in item
        for b in self.checklist.all():
        #if there is a checklist that is completed add 1
        if self.completed:
            total += 1
        return total

Вы можете использовать get_total

Не уверен, что это самый эффективный способ, но вы можете подсчитать общее количество списков и вычесть количество списков, в которых есть хотя бы один незавершенный пункт

from django.db.models import Count, Q, F

Flight.objects.annotate(
    checklist_count=Count('checklist', distinct=True),
    incomplete_checklists=Count('checklist', filter=Q(checklist__item__completed=False), distinct=True)
).annotate(
    completed_checklists=F('checklist_count') - F('incomplete_checklists')
)
Вернуться на верх