Подсчет детей, удовлетворяющих условиям внуков, в одном запросе 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')
)