如何在 Django 中创建带小数的数学运算 - [<class 'decimal.InvalidOperation'>]

How to create mathematics operations with decimal in Django - [<class 'decimal.InvalidOperation'>]

一个非常简单的保存方法导致了这个错误:

class Shift(models.Model):
    branch = models.ForeignKey(Branch, on_delete=models.CASCADE)
    employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
    start_time = models.DateTimeField(auto_now_add=True)
    end_time = models.DateTimeField(null=True)
    closing_type_amount = models.DecimalField(max_digits=4, decimal_places=2, default=0)
    closing_actual_amount = models.DecimalField(max_digits=4, decimal_places=2, default=0)
    diff = models.DecimalField(max_digits=4, decimal_places=2, null=True)
    on_duty = models.BooleanField(default=True)

    def save(self, *args, **kwargs):
        self.diff = float(self.closing_type_amount) - float(self.closing_actual_amount)
        super(Shift, self).save(*args, **kwargs)

这个错误的原因是行 self.diff = float(self.closing_type_amount) - float(self.closing_actual_amount) 注意 当输入超过 100 时它会失败,当像 5、4、6、11 这样的小数字时它会正常工作。

因为你设置的限制。 max_digits=4decimal_places=2 允许保存的最大数目为 99.99(小数位包含在最大位数中)。

查看用法示例 here

由于这些都是必需的参数,因此您可以设置足够高的值以适用于大多数用例。例如,以小数点后 10 位的分辨率存储最多约 10 亿的数字:

models.DecimalField(..., max_digits=19, decimal_places=10)

我还建议对您的模型进行一些更改,因为在我看来保存 diff 值是多余的,因为您已经有了计算它的两个值。而是将 属性 添加到您的模型以动态计算它:

class Shift(models.Model):
    branch = models.ForeignKey(Branch, on_delete=models.CASCADE)
    employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
    start_time = models.DateTimeField(auto_now_add=True)
    end_time = models.DateTimeField(null=True)
    closing_type_amount = models.DecimalField(max_digits=4, decimal_places=2, default=0)
    closing_actual_amount = models.DecimalField(max_digits=4, decimal_places=2, default=0)
    on_duty = models.BooleanField(default=True)

    @property
    def diff(self):
        return float(self.closing_type_amount) - float(self.closing_actual_amount)

此外,如果您要转换为 float,您不妨使用 FloatField 而不是 DecimalField。