2011-10-11 9 views
5

Tengo una relación de uno a muchos.campo de suma de modelos django de la relación de clave externa

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) 

Quiero hacer una consulta para seleccionar todas las filas de la factura y la suma del precio de todos los artículos para cada factura, y acceder a ella a través de un conjunto de consultas

por ejemplo, así que si invoice #1 tiene 2 items, cada uno con qty=2 y unit_price=3, invoice #1 tendría amount 2x2x3 = $12

ACTUALIZACIÓN:

Aquí es lo que tengo hasta ahora, pero me da un rastreo

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' 

ACTUALIZACIÓN

Gracias por las entradas, tomé algunas colas y en el Al final, creé una nueva columna unit_amount, agregué una acción adicional al método .save() para hacer prod_qty * unit_price y la guardé en la nueva columna.

y luego hicieron esto:

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

¿Seguro toda su UNIT_PRICE está int en su base de datos? –

Respuesta

2

Si select_related() entonces yo creo que deberías hacer .aggregate(sum=sum('unit_price')), ¿verdad? Todavía select_related() parece ser mucho.

También aggregate le dará un diccionario {sum:value}, por lo que el pedido parece ser un error? ¿Para qué sirve? Sin embargo, no estoy seguro de eso. :)

Si esto no funciona, ¿qué tal intentar esto un poco diferente?

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

Porque creo que quiere tener suma por factura, no suma global. Darle una oportunidad.

// EDITAR: Por supuesto, me olvidé de la cantidad. En ese caso, el código de infrarrojos es mejor.

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

Desde F() expresiones were refactoredin Django 1.8 Esto se ha convertido simple y directo:

from django.db.models import F, Sum 

Invoice.objects.annotate(Sum(F('item__unit_price') * F('item__qty'))) 
Cuestiones relacionadas