Django Aggregate-零值分区

Ada*_*rrh 9 django django-queryset

我正在使用Django的聚合查询表达式来总计一些值.最终值是一个除法表达式,有时可以将零作为分母.如果是这种情况,我需要一种方法来逃避,因此它只返回0.

我尝试了以下内容,因为我一直在使用类似我的注释表达式:

from django.db.models import Sum, F, FloatField, Case, When

def for_period(self, start_date, end_date):
    return self.model.objects.filter(
        date__range=(start_date, end_date)
    ).aggregate(
        sales=Sum(F("value")),
        purchase_cogs=Sum(F('purchase_cogs')),
        direct_cogs=Sum(F("direct_cogs")),
        profit=Sum(F('profit'))
    ).aggregate(
        margin=Case(
            When(sales=0, then=0),
            default=(Sum(F('profit')) / Sum(F('value')))*100
        )
    )
Run Code Online (Sandbox Code Playgroud)

但是,它显然不起作用,因为错误说:

'dict'对象没有属性'aggregate'

处理这个问题的正确方法是什么?

Muh*_*abi 12

这显然不起作用; 因为aggregate返回一个字典,而不是一个QuerySet(参见文档),所以你不能将两个aggregate调用链接在一起.

我认为使用annotate将解决您的问题.annotate几乎完全相同aggregate,除了它返回一个QuerySet,结果保存为属性而不是返回字典.其结果是,你可以链annotate来电,甚至打电话annotate然后aggregate.

所以我相信:

return self.model.objects.filter(
    date__range=(start_date, end_date)
).annotate(  # call `annotate`
    sales=Sum(F("value")),
    purchase_cogs=Sum(F('purchase_cogs')),
    direct_cogs=Sum(F("direct_cogs")),
    profit=Sum(F('profit'))
).aggregate(  # then `aggregate`
    margin=Case(
        When(sales=0, then=0),
        default=(Sum(F('profit')) / Sum(F('value')))*100
    )
)
Run Code Online (Sandbox Code Playgroud)

应该管用.

希望这可以帮助.