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

Joh*_*fis 4 python django

序幕:

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

也可以在这里应用:

我已经在SO文档中编写了一个示例,但由于文档将于2017年8月8日关闭,我将遵循这个广泛上升和讨论的元答案的建议,并将我的示例转换为自我回答的帖子.

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


题:

假设以下型号:

class MyModel(models.Model):
    number_1 = models.IntegerField()
    number_2 = models.IntegerField()
    date_1 = models.DateTimeField()
    date_2 = models.DateTimeField()
Run Code Online (Sandbox Code Playgroud)

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

例如,我如何找到:

  • MyModel对象的产品number_1和number_2?
  • 如何过滤date_210天或以上的物品date_1?

Joh*_*fis 9

F()表达式可以被用于执行算术运算(+,-,*模型字段之间等),以便限定在它们之间的代数查询/连接.

一个F()对象表示的值的模型字段或注释列.它可以引用模型字段值并使用它们执行数据库操作,而无需将它们从数据库中拉出到Python内存中.

让我们解决问题:

  • 两个领域的产物:

    result = MyModel.objects.all().annotate(prod=F('number_1') * F('number_2'))
    
    Run Code Online (Sandbox Code Playgroud)

    现在,在每一个项目result中有一个名为"刺"一个额外的列其中包含的产品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))
    
    Run Code Online (Sandbox Code Playgroud)

    现在的项目result是那些来自MyModel其date_2旧于10天以上date_1.这些项目有一个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')) 
    
    Run Code Online (Sandbox Code Playgroud)

  • 万一有人遇到问题: from django.db.models import F (2认同)