Можем ли мы сделать арифметику с использованием подзапросов Django? - PullRequest
0 голосов
/ 22 декабря 2018

Мне интересно, позволяет ли ORM в Django выполнять агрегирующие операции над вложенными вложениями, а затем выполнять арифметику с полученными значениями.

Как правильно поступить примерно так:

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 голосов
/ 22 декабря 2018

Вы, конечно, можете, но, насколько мне известно, вы не можете использовать aggregate().При попытке использовать aggregate() в Subquery django жалуется на попытку выполнить запрос, который имеет OuterRef s.То, как я это делаю (я действительно не знаю, если это так - в соответствии с документацией - ) - это использование 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

Я не запускал пример, поэтому может потребоваться некоторая корректировка здесь и там.

...