首页 > 解决方案 > 我们可以使用 Django 子查询进行算术运算吗?

问题描述

我想知道 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')

标签: djangodjango-querysetdjango-aggregation

解决方案


你当然可以,但据我所知,你不能使用aggregate(). 尝试aggregate()Subquerydjango 中使用时抱怨尝试执行具有OuterRefs 的查询。我这样做的方式(我真的不知道这是否是方式- 根据文档是 -)是使用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

我没有运行这个例子,所以它可能需要在这里和那里进行一些调整。


推荐阅读