2011-10-11 23 views
5

Tôi có mối quan hệ một đến nhiều.trường mô hình django tổng hợp từ mối quan hệ khóa ngoài

class Invoice(models.Model): 
    stuff 

class Item(models.Model): 
    invoice = models.ForeignKey(Invoice) 
    qty = models.IntegerField() 
    unit_price = models.DecimalField(max_digits=4, decimal_places=2) 

Tôi muốn thực hiện một truy vấn để chọn tất cả các hàng trong hóa đơn và tổng của các giá của tất cả các mặt hàng cho mỗi hóa đơn, và truy cập nó thông qua một queryset

ví dụ vì vậy nếu invoice #12 items, mỗi qty=2unit_price=3, invoice #1 sẽ phải amount 2x2x3 = $12

UPDATE:

Dưới đây là những gì tôi có cho đến nay nhưng nó mang lại cho tôi một traceback

inv_list = \ 
Invoice.objects.select_related().all()\ 
.aggregate(sum=sum('item__unit_price')).order_by('-inv_date') 

TypeError at /site/invoice/ 
unsupported operand type(s) for +: 'int' and 'str' 

CẬP NHẬT

Cảm ơn các yếu tố đầu vào, tôi đã lấy một số hàng đợi và trong cuối cùng tôi đã tạo một cột mới unit_amount, đã thêm một hành động bổ sung vào phương thức .save() để làm prod_qty * unit_price và lưu nó vào cột mới.

và sau đó đã làm điều này:

inv_list = Invoice.objects.all()\ 
.annotate(amount=Sum('item__unit_amount')).order_by('-inv_date') 
+0

Bạn có chắc chắn tất cả unit_price của bạn là int trong cơ sở dữ liệu của bạn? –

Trả lời

2

Nếu bạn select_related() sau đó tôi nghĩ rằng bạn nên làm .aggregate(sum=sum('unit_price')), phải không? Vẫn còn select_related() dường như là cách để nhiều.

Ngoài ra aggregate sẽ cung cấp cho bạn một từ điển {sum:value}, vì vậy việc đặt hàng có vẻ là một sai lầm? Nó là gì? Không chắc chắn về điều đó mặc dù. :)

Nếu cách này không hiệu quả, hãy thử cách này khác một chút?

for invoice in Invoice.objects.all(): 
    tmp = invoice.item_set.aggregate(sum=sum('unit_price')) 
    # do some stuff with sum 

Bởi vì tôi tin rằng bạn muốn có tổng cho mỗi hóa đơn chứ không phải tổng trên toàn cầu. Hãy thử một lần.

// EDIT: Tất nhiên tôi quên số lượng. Trong trường hợp đó mã của hồng ngoại là tốt hơn.

2
for invoice in Invoice.objects.all(): 
    ammount = 0 
    for item in invoice.item_set.all(): 
     ammount += item.qty * item.unit_price 
     print invoice.pk, ammount 
2

Kể từ F() biểu were refactoredin Django 1.8 này đã trở nên đơn giản và dễ hiểu:

from django.db.models import F, Sum 

Invoice.objects.annotate(Sum(F('item__unit_price') * F('item__qty'))) 
Các vấn đề liên quan