2011-10-11 17 views
5

Ho una relazione uno a molti.modelli django sommano il campo dalla relazione di chiave esterna

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) 

Voglio fare una query per selezionare tutte le righe della fattura e la somma del prezzo di tutti gli elementi per ogni fattura, e accedervi attraverso un set di query

esempio quindi se invoice #1 ha 2 items, ognuno con qty=2 e unit_price=3, invoice #1 avrebbe amount 2x2x3 = $12

UPDATE:

Ecco quello che ho finora ma mi dà un 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' 

UPDATE

Grazie per gli input, ho preso alcune code e nel Alla fine ho creato una nuova colonna unit_amount, aggiunta un'azione aggiuntiva al metodo .save() per fare prod_qty * unit_price e salvarla nella nuova colonna.

e poi ha fatto questo:

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

Sei sicuro tutti i vostri unit_price siete int nel database? –

risposta

2

Se select_related() allora penso che si dovrebbe fare .aggregate(sum=sum('unit_price')), giusto? Ancora select_related() sembra essere il modo di molto.

Anche aggregate ti darà un dizionario {sum:value}, quindi l'ordine sembra essere un errore? Cosa serve? Non sono sicuro di ciò, comunque. :)

Se questo non funziona, provate a farlo un po 'diverso?

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

Perché credo che si desidera avere una somma per fattura, non somma globale. Provaci.

// EDIT: Ovviamente ho dimenticato la quantità. In tal caso, il codice a infrarossi è migliore.

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

Dal F() espressioni were refactoredin Django 1.8 questo è diventato semplice e diretto:

from django.db.models import F, Sum 

Invoice.objects.annotate(Sum(F('item__unit_price') * F('item__qty'))) 
Problemi correlati