简体   繁体   English

Django 聚合:两个字段相乘的总和

[英]Django Aggregation: Summation of Multiplication of two fields

I have a model something like this:我有一个这样的模型:

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

Now I would like to do a calculation Sum(progress * estimated_days) on the database level.现在我想在数据库级别做一个计算Sum(progress * estimated_days) Using Django Aggregation I can have the sum for each field but not the summation of multiplication of fields.使用 Django 聚合,我可以得到每个字段的总和,但不能得到字段乘法的总和。

With Django 1.8 and above you can now pass an expression to your aggregate:使用 Django 1.8 及更高版本,您现在可以将表达式传递给聚合:

 from django.db.models import F

 Task.objects.aggregate(total=Sum(F('progress') * F('estimated_days')))['total']

Constants are also available, and everything is combinable:常量也可用,一切都可以组合:

 from django.db.models import Value

 Task.objects.aggregate(total=Sum('progress') / Value(10))['total']

Update: for Django >= 1.8 please follow the answer provided by @kmmbvnr更新:对于Django >= 1.8,请按照@kmmbvnr 提供的答案进行操作

it's possible using Django ORM:可以使用 Django ORM:

here's what you should do:这是你应该做的:

from django.db.models import Sum

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

Note: if the two fields are of different types, say integer & float , the type you want to return should be passed as the first parameter of Sum注意:如果两个字段的类型不同,比如integer & float ,你要返回的类型应该作为Sum的第一个参数传递

It's a late answer, but I guess it'll help someone looking for the same.这是一个迟到的答案,但我想它会帮助寻找相同答案的人。

The solution depends on Django version.解决方案取决于 Django 版本。

  • django < 1.8 Django < 1.8

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

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

Do you have several options:你有几个选择:

  1. Raw query原始查询
  2. Emulbreh's undocumented approach Emulbreh 的无证方法
  3. Create a third field progress_X_estimated_days and update it in save overwrited method.创建第三个字段progress_X_estimated_days并在保存覆盖方法中更新它。 Then do aggregation through this new field.然后通过这个新字段进行聚合。

Overwriting:覆盖:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM