如何在Django中使用条件计数?

时间:2018-05-06 16:57:03

标签: python django

假设我们有以下简单模型:

qs = Product.objects.all().values("category__name").annotate(total_products=Count("id"), total_available=Cast((Count(Case(When(status__name__in=["Sold", "Reserved"], then=True), output_field=BooleanField())) / Count("id")) * 100., FloatField()))

状态选择包括:已售出,未售出,已保留,撤回。

我的目标是每个类别获得产品总数以及销售或预留的数量占每个类别总数的百分比:

{{1}}

对于某些类别,会返回正确的结果,而对于其他类别则不会。

1 个答案:

答案 0 :(得分:0)

您需要先将sold_count和reserved_count与total_count一起注释,然后再使用它进行注释。像下面这样的东西应该有效:

from django.db import models


status_list = [
    'Sold',
    'Reserved',
]
# Build Case query
count_query = {}
percent_query = {}
for status in status_list:
    count_key = '{}_count'.format(status.lower())
    count_query[count_key] = models.Sum(
        models.Case(
            models.When(
                status__name=status,
                then=models.Value(1.0)
            ),
            default=0.0,
            output_field=models.FloatField()
        ))

    percent_key = '{}_percent'.format(status.lower())
    percent_query[percent_key] = models.ExpressionWrapper(
        models.F(count_key) / models.F('total_products') * 100.0,
        output_field=models.FloatField()
    )


queryset = Product.objects.values('category__name').annotate(
    total_products=models.Count('id'),
    **count_query
)
queryset = queryset.annotate(**percent_query)

对于Django> = 2.0

使用Conditional Aggregation

有更好的实施方式