Django Annotate- 沿多个 .annotate() 函数分组
Django Annotate- Grouping along multiple .annotate() functions
我有以下管理器,它工作正常。
def by_customer_and_date(self, start_date, end_date):
qs = self.model.objects.filter(
date__range=(start_date, end_date)
).values(
"customer__name"
).annotate(
grand_total_cogs=Sum('total_cogs'),
total_sales=Sum('value'),
total_profit=Sum('profit'),
total_kgs=Sum('qty_applied'),
current_balance=Sum('sale__receiptallocation__qty_applied')
).order_by('-total_kgs')
使用 .values("customer__name")
按客户名称properly grouped 结果
但是,我想做的是:
def by_customer_and_date(self, start_date, end_date):
qs = self.model.objects.filter(
date__range=(start_date, end_date)
).values(
"customer__name"
).annotate(
grand_total_cogs=Sum('total_cogs'),
total_sales=Sum('value'),
total_profit=Sum('profit'),
total_kgs=Sum('qty_applied'),
current_balance=Sum('sale__receiptallocation__qty_applied')
).annotate(
margin=Case(
When(total_sales=0, then=0),
default=(F('profit')) / (F('value'))*100
)
).order_by('-total_kgs')
我正在使用带注释的值来计算另一个分母可能为零的值(因此使用 Case(When)
)。当我添加这部分时,.values("customer__name")
函数失去它的作用,并且显示每个单独的项目。
我试过将 .values("customer__name")
部分移到末尾(添加了对每个字段名称的显式引用),但问题仍然存在。
这是预期的行为吗?有什么办法可以解决这个问题吗?
我确定第二个 annotate()
必须放在表达式的最后。在我的示例中,它们的正确顺序应如下所示:
self.model.objects.filter().values().annotate().order_by().annotate()
结果如下:
def by_customer_and_date(self, start_date, end_date):
qs = self.model.objects.filter(
date__range=(start_date, end_date)
).values(
"customer__name"
).annotate(
grand_total_cogs=Sum('total_cogs'),
total_sales=Sum('value'),
total_profit=Sum('profit'),
total_kgs=Sum('qty_applied'),
current_balance=Sum('sale__receiptallocation__qty_applied'),
).order_by(
'-total_kgs'
).annotate(
final_margin=Case(
When(total_sales=0, then=0),
default=(Sum(F('profit')) / Sum(F('value')))*100
)
)
return qs
我有以下管理器,它工作正常。
def by_customer_and_date(self, start_date, end_date):
qs = self.model.objects.filter(
date__range=(start_date, end_date)
).values(
"customer__name"
).annotate(
grand_total_cogs=Sum('total_cogs'),
total_sales=Sum('value'),
total_profit=Sum('profit'),
total_kgs=Sum('qty_applied'),
current_balance=Sum('sale__receiptallocation__qty_applied')
).order_by('-total_kgs')
使用 .values("customer__name")
但是,我想做的是:
def by_customer_and_date(self, start_date, end_date):
qs = self.model.objects.filter(
date__range=(start_date, end_date)
).values(
"customer__name"
).annotate(
grand_total_cogs=Sum('total_cogs'),
total_sales=Sum('value'),
total_profit=Sum('profit'),
total_kgs=Sum('qty_applied'),
current_balance=Sum('sale__receiptallocation__qty_applied')
).annotate(
margin=Case(
When(total_sales=0, then=0),
default=(F('profit')) / (F('value'))*100
)
).order_by('-total_kgs')
我正在使用带注释的值来计算另一个分母可能为零的值(因此使用 Case(When)
)。当我添加这部分时,.values("customer__name")
函数失去它的作用,并且显示每个单独的项目。
我试过将 .values("customer__name")
部分移到末尾(添加了对每个字段名称的显式引用),但问题仍然存在。
这是预期的行为吗?有什么办法可以解决这个问题吗?
我确定第二个 annotate()
必须放在表达式的最后。在我的示例中,它们的正确顺序应如下所示:
self.model.objects.filter().values().annotate().order_by().annotate()
结果如下:
def by_customer_and_date(self, start_date, end_date):
qs = self.model.objects.filter(
date__range=(start_date, end_date)
).values(
"customer__name"
).annotate(
grand_total_cogs=Sum('total_cogs'),
total_sales=Sum('value'),
total_profit=Sum('profit'),
total_kgs=Sum('qty_applied'),
current_balance=Sum('sale__receiptallocation__qty_applied'),
).order_by(
'-total_kgs'
).annotate(
final_margin=Case(
When(total_sales=0, then=0),
default=(Sum(F('profit')) / Sum(F('value')))*100
)
)
return qs