没有关系时计数并返回零的注释

时间:2018-09-12 08:09:22

标签: django django-queryset

给出以下关系:

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'))

我可以找到实现此目标的另一种方法,但我想知道是否可以通过注释来实现。

我正在使用

2 个答案:

答案 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)

及更高版本中,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))
    )
)

对于及以下版本,我们可以使用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()
    ))
)
相关问题