Django аннотирует поля с нулевыми значениями
У меня есть список Demand объектов, имеющих allocated поле, которое либо будет null, либо будет иметь имя (обозначающее выделение этого требования).
Я использую аннотации для подсчета выделенных/невыделенных номеров на команду:
Demand.objects.filter(project=project).values('team').annotate(
unallocated=Count('allocated', filter=Q(allocated__isnull=True)),
allocated=Count('allocated', filter=Q(allocated__isnull=False))
)
Странно то, что числа для аннотации allocated выходят правильными, но числа для unallocated всегда равны нулю.
Например:
list(Demand.objects.filter(project=project).values('allocated', 'team'))
Со следующим результатом:
[{'allocated': None, 'team': 'Design'},
{'allocated': None, 'team': 'Engineering'},
{'allocated': None, 'team': 'Engineering'},
{'allocated': None, 'team': 'Engineering'},
{'allocated': None, 'team': 'Delivery'},
{'allocated': None, 'team': 'Product'}]
но в аннотации к нему есть только это:
<QuerySet
[{'team': 'Delivery', 'unallocated': 0, 'allocated': 0},
{'team': 'Design', 'unallocated': 0, 'allocated': 0},
{'team': 'Engineering', 'unallocated': 0, 'allocated': 0},
{'team': 'Product', 'unallocated': 0, 'allocated': 0}]>
Я делаю это неправильно или это может быть ошибка?
Это потому, что Count(…) [Django-doc] не считает NULL, именно так SQL определяет работу агрегата COUNT: он не учитывает NULL значения (это также относится и к AVG, например). Но вы можете вместо этого считать первичный ключ, например:
from django.db.models import Count, Q
Demand.objects.filter(project=project).values('team').annotate(
unallocated=Count('pk', filter=Q(allocated=None)),
allocated=Count('allocated', filter=Q(allocated__isnull=False))
).order_by('team')
Также можно упростить allocated до:
from django.db.models import Count, Q
Demand.objects.filter(project=project).values('team').annotate(
unallocated=Count('pk', filter=Q(allocated=None)),
allocated=Count('allocated')
).order_by('team')