创建或字段更改时的触发器模型方法

时间:2018-01-06 17:20:01

标签: python django

假设我在django中有这个模型:

class Example(models.Model):
    name = models.CharField(max_length=100)
    number = models.IntegerField(unique=True)
    x = models.FloatField(null=True)
    y = models.FloatField(null=True)
    z = models.FloatField(null=True)
    v = models.FloatField(null=True)

    def get_z(self):
        z = x / y
        self.z = z
        self.save()

    def get_v(self):
        v = z * x
        self.v = v
        self.save()

当我使用管理面板创建对象时,我只提供名称,数字,x和y字段。我需要z和v字段自动计算对象创建或任何字段更改它们的值。目前它正在制作:

 z_value = property(get_z)

并将z_value放在管理面板中的list_display中,然后当我去那里时,会保存值。

1 个答案:

答案 0 :(得分:2)

您可以像这样覆盖安全方法:

class Example(models.Model):
    ...
    x = models.FloatField(null=True)
    y = models.FloatField(null=True)
    z = models.FloatField(null=True)
    v = models.FloatField(null=True)

    def save(self, *args, **kwargs):
        self.z = self.x / self.y
        self.v = self.z * self.x
        super(Example, self).save(*args, **kwargs)

在保存期间填充字段的原因是它可以使查询更容易。但也有缺点。例如,您必须确保永远不要在这些字段上使用update()。更新时不会调用save方法!

所以写一个这样的规范化模型可能会更好:

class Example(models.Model):
    ...
    x = models.FloatField(null=True)
    y = models.FloatField(null=True)

    @property
    def z(self):
        return self.x / self.y

    @property
    def v(self):
        return self.z * self.x

要在查询集中对z和v执行任何操作,您必须注释字段。像这样:

Example.objects.annotate(z=Sum(F('x') / F('y'))).annotate(v=Sum(F('z') * F('x')))