通过在 2 个字段上应用聚合在 Django 中创建评估字段

问题描述

我正处于学习 Django 框架的阶段,我需要一些帮助来理解如何通过总结用户的两个输入来生成评估字段。我使用了下面的代码,其中 ops1ops2 将由用户提供,我需要在运行时在字段 total_ops 中显示它们的总和。我使用了下面的代码,但这似乎不起作用。

class ManHour(models.Model):
    date      = models.DateTimeField(auto_now=True)

    class Operations(models.Model):
         ops1  = models.DecimalField(max_digits= 5,decimal_places= 3)
         ops2  = models.DecimalField(max_digits= 5,decimal_places= 3)
    
    total_ops = Operations.ops1 + Operations.ops2

上面代码错误

TypeError: unsupported operand type(s) for +: 'DeferredAttribute' and 'DeferredAttribute'

解决方法

模型是您定义字段及其属性的地方。

所以 total_ops 将是一个 DecimalField。

现在您可以在模型中应用业务逻辑。但建议使用视图集或表单保存它。

由于您仍在学习,因此对于此特定查询,您可以执行以下操作:

class Operations(models.Model):
     ops1  = models.DecimalField(max_digits= 5,decimal_places= 3)
     ops2  = models.DecimalField(max_digits= 5,decimal_places= 3)
     total_ops = models.DecimalField(max_digits= 5,decimal_places= 3)

     def save(self):
         self.total_ops = self.ops1 + self.ops2
         return super(Operations,self).save()
,

当你想根据模型对象的其他字段计算一个字段时,你应该使用 F() 表达式。它在 django 文档中描述 https://docs.djangoproject.com/en/3.2/ref/models/instances/#updating-attributes-based-on-existing-fields (https://docs.djangoproject.com/en/3.1/ref/models/expressions/#django.db.models.F)

所以如果你想用另一个字段的值保存一个字段,它应该是这样的:

operations  # Model instance
operations.total_ops = F("ops1") + F("ops2")
operations.save()

save() 方法中这样做是有风险的,因为在使用 queryset.update()queryset.create()queryset.bulk_create() 等时不会执行此操作。

在保存对象之前执行操作应该使用 pre_save 信号完成,您可以在保存对象之前修改实例字段:

@receiver(pre_save)
def save_calculated_field(sender,instance=None,**kwargs):
    instance.total_ops = F("ops1") + F("ops2")

但在大多数情况下也不推荐这样做,因为信号不会在 queryset.create()queryset.update() 等上执行。

Soooo,怎么做这个???

查询时使用annotate计算数据库中的字段值,一直跳过保存到数据库

from django.db.models import F

Operations.objects.annotate(
    total_ops=F("ops1") + F("ops2"),)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...