我有一个类似下面的模型:
class Task(models.Model):
progress = models.PositiveIntegerField()
estimated_days = models.PositiveIntegerField()
现在我想在数据库层面上执行一个计算 Sum(progress * estimated_days)
。使用Django聚合,我可以为每个字段获得总和,但无法获得字段乘积的总和。
我有一个类似下面的模型:
class Task(models.Model):
progress = models.PositiveIntegerField()
estimated_days = models.PositiveIntegerField()
现在我想在数据库层面上执行一个计算 Sum(progress * estimated_days)
。使用Django聚合,我可以为每个字段获得总和,但无法获得字段乘积的总和。
从Django 1.8及以上版本开始,您可以将表达式传递给聚合函数:
from django.db.models import F
Task.objects.aggregate(total=Sum(F('progress') * F('estimated_days')))['total']
还有常量可用,一切都可以组合:
from django.db.models import Value
Task.objects.aggregate(total=Sum('progress') / Value(10))['total']
更新:对于 Django >= 1.8 版本,请参照 @kmmbvnr 提供的回答。
可以使用 Django ORM 实现:
下面是具体步骤:
from django.db.models import Sum
total = ( Task.objects
.filter(your-filter-here)
.aggregate(
total=Sum('progress', field="progress*estimated_days")
)['total']
)
integer
和 float
,你想要返回的类型应该作为 Sum
的第一个参数传递。Sum
的第一个参数吧?那么,正如我所提到的,如果这两个字段是不同类型的,比如整数和浮点数,你想要返回的类型应该作为 Sum 的第一个参数传递。 - sha256解决方案取决于Django版本。
django < 1.8
from django.db.models import Sum
MyModel.objects.filter(<filters>).aggregate(Sum('field1', field="field1*field2"))
django >= 1.8
from django.db.models import Sum, F
MyModel.objects.filter(<filters>).aggregate(Sum(F('field1')*F('field2')))
在Django 1.8版本之后
自Django 1.8版本开始,您可以使用F
:
from django.db.models import F. Sum
total = (
Task
.objects
.aggregate(total=Sum(F('progress') * F('estimated_days')))
['total']
)
旧答案(Django 1.8之前)
本答案写于2012年,Django 1.8于2015年发布。
你有几个选项:
progress_X_estimated_days
并在保存覆盖方法中更新它。然后通过这个新字段进行聚合。覆盖:
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)
AttributeError:'ExpressionNode'对象没有'split'属性
的错误。我的Django版本是1.7.10。 - Grijesh Chauhanprogress
是其他模型的外键,例如让它成为Product
并且它有一个字段price
,那么应该如何重新格式化它?Task.objects.aggregate(total=Sum(F('progress.price') * F('estimated_days')))['total']
无法工作。 - ANFAS PV