Django Sum 带注释的字段
我试图首先对 Python 中的带注释字段进行求和
,
class InvoiceItems(models):
units = FloatField(...)
price = FloatField(...)
sku = CharField(...)
所以我想对 units * Price
进行注释,然后对它们进行 Sum()
对于给定的 sku
但
qs = InvoiceItems.annotate(
amount=Sum(F('units')*F('price'), output_field=models.FloatField())
)
不起作用。
我的实际代码:
def customer_purchase_detail(**kwargs):
from_date = kwargs.get('from_date', False)
to_date = kwargs.get('to_date', False)
channel = kwargs.get('channel', False)
customer = kwargs.get('customer', False)
sku = kwargs.get('sku', False)
query_set = Invoice.objects.filter(
record_type=3,
)
if from_date:
query_set = query_set.filter(date__gte=datetime.datetime.strptime(from_date, '%Y-%m-%d'))
if to_date:
query_set = query_set.filter(date__lte=datetime.datetime.strptime(to_date, '%Y-%m-%d'))
if channel:
query_set = query_set.filter(order__customer__category=channel)
if customer:
query_set = query_set.filter(order__customer__code=customer)
if sku:
query_set = query_set.filter(order__orderitem__product__sku=sku)
query_set = query_set.annotate(
amount=Sum(
((F('order__orderitem__order_quantity') - F('order__orderitem__cancel_quantity')) * F(
'order__orderitem__unit_price')) - F('order__orderitem__discount_amount'),
output_field=models.FloatField()
),
quantity=Sum(
(F('order__orderitem__order_quantity') - F('order__orderitem__cancel_quantity') -
F('order__orderitem__remove_quantity')) *
F('order__orderitem__pieces_per_unit'),
output_field=models.IntegerField()
)
)
query_set = query_set.values(
'order__orderitem__product__sku',
'order__orderitem__product__description',
'order__orderitem__product__description_en',
'amount',
'quantity'
).order_by('-amount').all()
total = reduce(lambda acc, x: acc + x['amount'], query_set, 0)
result = [
{
'sku': q['order__orderitem__product__sku'],
'name': q['order__orderitem__product__description'],
'name_en': q['order__orderitem__product__description_en'],
'amount': q['amount'],
'quantity': q['quantity'],
'ppu': round((q['amount'] / q['quantity']) if q['quantity'] > 0 else 0),
'pct': round(q['amount'] / total, 3)
}
for q in query_set
]
# Made this a list for JsonResponse() that this query returns to
return result
如果我的表是
sku | unit | price
AA | 2 | 1.00
AA | 3 | 2.00
AA | 5 | 2.00
BB | 4 | 1.00
我想要的结果
sku | amount
AA | 18
BB | 4
,但 Django 发送的结果集是,
sku | amount
AA | 8
AA | 10
BB | 4
所以对一些集合而不是其他集合进行求和和分组。 PS我注意到在这个简单的例子中,它的工作原理就像我让它与另一个查询一起工作一样。不知何故,这与此无关。 任何建议将不胜感激!谢谢!
I'm trying to sum an annotated field in Python
First,
class InvoiceItems(models):
units = FloatField(...)
price = FloatField(...)
sku = CharField(...)
So I want to annotate
the units * price
then Sum()
them all up for a given sku
but
qs = InvoiceItems.annotate(
amount=Sum(F('units')*F('price'), output_field=models.FloatField())
)
isn't working.
My actual code:
def customer_purchase_detail(**kwargs):
from_date = kwargs.get('from_date', False)
to_date = kwargs.get('to_date', False)
channel = kwargs.get('channel', False)
customer = kwargs.get('customer', False)
sku = kwargs.get('sku', False)
query_set = Invoice.objects.filter(
record_type=3,
)
if from_date:
query_set = query_set.filter(date__gte=datetime.datetime.strptime(from_date, '%Y-%m-%d'))
if to_date:
query_set = query_set.filter(date__lte=datetime.datetime.strptime(to_date, '%Y-%m-%d'))
if channel:
query_set = query_set.filter(order__customer__category=channel)
if customer:
query_set = query_set.filter(order__customer__code=customer)
if sku:
query_set = query_set.filter(order__orderitem__product__sku=sku)
query_set = query_set.annotate(
amount=Sum(
((F('order__orderitem__order_quantity') - F('order__orderitem__cancel_quantity')) * F(
'order__orderitem__unit_price')) - F('order__orderitem__discount_amount'),
output_field=models.FloatField()
),
quantity=Sum(
(F('order__orderitem__order_quantity') - F('order__orderitem__cancel_quantity') -
F('order__orderitem__remove_quantity')) *
F('order__orderitem__pieces_per_unit'),
output_field=models.IntegerField()
)
)
query_set = query_set.values(
'order__orderitem__product__sku',
'order__orderitem__product__description',
'order__orderitem__product__description_en',
'amount',
'quantity'
).order_by('-amount').all()
total = reduce(lambda acc, x: acc + x['amount'], query_set, 0)
result = [
{
'sku': q['order__orderitem__product__sku'],
'name': q['order__orderitem__product__description'],
'name_en': q['order__orderitem__product__description_en'],
'amount': q['amount'],
'quantity': q['quantity'],
'ppu': round((q['amount'] / q['quantity']) if q['quantity'] > 0 else 0),
'pct': round(q['amount'] / total, 3)
}
for q in query_set
]
# Made this a list for JsonResponse() that this query returns to
return result
If my table is
sku | unit | price
AA | 2 | 1.00
AA | 3 | 2.00
AA | 5 | 2.00
BB | 4 | 1.00
I want the result
sku | amount
AA | 18
BB | 4
but the result set Django is sending out is
sku | amount
AA | 8
AA | 10
BB | 4
So summing and grouping some sets, not others.
P.S. I noticed that in the simple example, it works as I have it working with another query. Somehow it doesn't with this one.
Any advice would be appreciated! Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该按
sku
进行分组,因此:这将创建一个字典的
QuerySet
,因此:话虽这么说,最好创建一个
Product 模型,因此对该
Product
使用ForeignKey
而不是sku
。You should group by the
sku
, so:This will make a
QuerySet
of dictionaries, so:That being said, it might be better to make a
Product
model, and thus use aForeignKey
to thatProduct
instead of asku
.我不知道为什么这有效,但我
在
注释
之后移动了过滤器,现在一切正常了。I don't know why this works, but I moved my filters
after the
annotate
and all works now.