我们可以使用Django子查询进行算术运算吗?

时间:2018-12-22 00:39:00

标签: django django-queryset django-aggregation

我想知道Django的ORM是否允许我们对子查询进行聚合操作,然后对结果值进行算术运算。

做这样的事情的正确方法是什么?

record = PackingRecord.objects.filter(product=OuterRef('pk'))
packed = FifoLink.objects.filter(packing_record__product=OuterRef('pk'))

output = obj_set.annotate(
    in_stock=(Subquery(record.aggregate(Sum('qty'))) - Subquery(packed.aggregate(Sum('sale__qty'))))
).values('id', 'name', 'in_stock')

1 个答案:

答案 0 :(得分:1)

您当然可以,但是据我所知,您不能使用aggregate()。尝试在aggregate()中使用Subquery时,django抱怨试图执行具有OuterRef的查询。我这样做的方式(我真的不知道这是否是- according to the docs it is -的方式)是通过使用annotate()来实现的。在您的示例中遇到的情况下,我将执行以下操作:

records_total = (PackingRecord.objects.filter(product=OuterRef('pk'))
    .values('product') # Group by product
    .annotate(total=Sum('qty')) # Sum qty for 'each' product
    .values('total')
)
packed_total = (FifoLink.objects.filter(packing_record__product=OuterRef('pk'))
    .values('packing_record__product') # Group by packing_record__product
    .annotate(total=Sum('sale__qty')) # Sum sale__qty for 'each' product
    .values('total')
)
output = obj_set.annotate(
    r_tot=Subquery(record_total[:1]),
    p_tot=Subquery(packed_total[:1])
).annotate(
    in_stock=F('r_tot')-F('p_tot')
) # Whatever you need

我没有运行该示例,因此可能需要在此处和此处进行一些调整。