给出以下关系:
class LicenseRequest:
license_type = models.ForeignKey(LicenseType)
created_at = models.DateField(default=now, editable=False)
class LicenseType:
name = models.CharField(max_length=100)
value = models.CharField(max_length=3, unique=True)
我想计算每种许可证类型创建了多少个请求。但是,由于我正在生成图形,因此对于该许可证类型,在该特定时间段内,如果没有任何许可证请求,则必须包括0(零)。
我尝试执行建议的here,但没有成功。我只能从具有多个许可请求的许可类型中获得计数。
qs = LicenseType.objects.filter(
Q(licenserequest__created_at__range=(start_date, end_date)) | Q(licenserequest__isnull=True)
).annotate(rel_count=Count('licenserequest__id'))
我可以找到实现此目标的另一种方法,但我想知道是否可以通过注释来实现。
我正在使用django1.11.15。
答案 0 :(得分:2)
qs = LicenseType.objects.annotate(count=Count('licenserequest__id')
condition = Q(licenserequest__created_at__range=(start_date, end_date)) & Q(licenserequest__isnull=True)
qs = qs.annotate(Case(When(condition, then=F('count')), default=0, output_field=IntegerField())
这应该适用于您提供的模型描述。 要进行以后的过滤,您不能使用直接的.filter()而是使用Case / When .annotate()子句
答案 1 :(得分:2)
在djang-2.0及更高版本中,Count
对象具有一个filter
参数,因此我们可以为此指定编码:
qs = LicenseType.objects.annotate(
rel_count=Count(
'licenserequest',
filter=Q(licenserequest__created_at__range=(start_date, end_date))
)
)
qs = LicenseType.objects.annotate(
rel_count=Count(
'licenserequest',
filter=Q(licenserequest__created_at__range=(start_date, end_date))
)
)
对于djang-1.11及以下版本,我们可以使用Sum(..)
表达式的Case(..)
:
qs = LicenseType.objects.annotate(
rel_count=Sum(Case(
When(
licenserequest__created_at__range=(start_date, end_date),
then=1
),
default=0,
output_field=IntegerField()
))
)