Agregación de Django: Suma de la multiplicación de dos campos

Tengo un modelo algo como esto

class Task(models.Model): progress = models.PositiveIntegerField() estimated_days = models.PositiveIntegerField() 

Ahora me gustaría hacer un cálculo de Sum(progress * estimated_days) en el nivel de la base de datos. Usando la Agregación de Django puedo tener la sum para cada campo pero no la sum de la multiplicación de campos.

Actualización: para Django> = 1.8 , siga la respuesta provista por @kmmbvnr

Es posible usar Django ORM:

Esto es lo que debes hacer:

 from django.db.models import Sum total = ( Task.objects .filter(your-filter-here) .aggregate( total=Sum('progress', field="progress*estimated_days") )['total'] ) 

Nota: si los dos campos son de diferentes tipos, digamos integer & float , el tipo que desea devolver debe pasarse como el primer parámetro de Sum

Es una respuesta tardía, pero creo que ayudará a alguien que busca lo mismo.

Con Django 1.8 y superior ahora puedes pasar una expresión a tu agregado:

  from django.db.models import F Task.objects.aggregate(total=Sum(F('progress') * F('estimated_days')))['total'] 

Las constantes también están disponibles, y todo es combinable:

  from django.db.models import Value Task.objects.aggregate(total=Sum('progress') / Value(10))['total'] 

La solución depende de la versión de Django.

  • django <1.8

     from django.db.models import Sum MyModel.objects.filter().aggregate(Sum('field1', field="field1*field2")) 
  • django> = 1.8

     from django.db.models import Sum, F MyModel.objects.filter().aggregate(Sum(F('field1')*F('field2'))) 

Tienes varias opciones:

  1. Consulta en bruto
  2. El enfoque indocumentado de Emulbreh
  3. Cree un tercer campo progress_X_estimated_days y actualícelo en el método de sobreescritura de guardado. Entonces haz agregación a través de este nuevo campo.

Sobrescribiendo

 class Task(models.Model): progress = models.PositiveIntegerField() estimated_days = models.PositiveIntegerField() progress_X_estimated_days = models.PositiveIntegerField(editable=False) def save(self, *args, **kwargs): progress_X_estimated_days = self.progress * self.estimated_days super(Task, self).save(*args, **kwargs)