如何在django中的模型字段之间执行算术运算

序幕:

这是SO中经常出现的问题:

> Subtracting two annotated columns
> Django query with simple arithmetic among model fields and comparison with field from another model
> Django Aggregation: Summation of Multiplication of two fields

也可以在这里应用:

> Django F expression on datetime objects

我已经在SO文档中编写了一个示例,但由于文档将于2017年8月8日关闭,我将遵循this widely upvoted and discussed meta answer的建议并将我的示例转换为自我回答的帖子.

当然,我也很乐意看到任何不同的方法!

题:

假设以下型号:

class MyModel(models.Model):
    number_1 = models.IntegerField()
    number_2 = models.IntegerField()
    date_1 = models.DateTimeField()
    date_2 = models.DateTimeField()

如何在此模型的字段之间执行算术运算?

例如,我如何找到:

> MyModel对象的number_1和number_2的乘积?
>如何过滤date_2比date_1早10天或更多天的项目?

最佳答案
F()表达式可用于在模型字段之间执行算术运算(, – ,*等),以便在它们之间定义代数查找/连接.

An F() object represents the value of a model field or annotated column. It makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory.

让我们解决问题:

>两个领域的产物:

result = MyModel.objects.all().annotate(prod=F('number_1') * F('number_2'))

现在,结果中的每个项目都有一个名为“prod”的额外列,其中包含每个项目的number_1和number_2的乘积.
>按天差异过滤:

from datetime import timedelta

result = MyModel.objects.all().annotate(
             delta=F('date_2') - F('date_1')
         ).filter(delta__gte=timedelta(days=10))

现在,结果中的项目来自MyModel,其date_2比date_1早10天或更多天.这些项目有一个名为delta的新列,具有该差异.
>一个不同的案例:

我们甚至可以使用F()表达式对带注释的列进行算术运算,如下所示:

result = MyModel.objects.all()
                        .annotate(sum_1=Sum('number_1'))
                        .annotate(sum_2=Sum('number_2'))
                        .annotate(sum_diff=F('sum_2') - F('sum_1')) 
点赞