在Django模型中设置局部变量

时间:2019-01-16 11:36:32

标签: django django-models

我有以下模型:

class MeasurementParameter(models.Model):    
    tolerance = models.FloatField()
    set_value = models.FloatField()

    tol_low = None
    tol_high = None

    def tolerance_band(self):

        tol = self.set_value * self.tolerance/100

        self.tol_high = self.set_value + tol
        self.tol_low = self.set_value - tol

        print self.tol_low

        return self.tol_high, self.tol_low

我希望使用tolerance_band方法将计算出的局部变量设置为tol_low和tol_high。

该模型与另一个名为Product的模型具有ManyToMany关系。

class Product(models.Model):
    name = models.CharField(max_length=100)
    description = models.CharField(max_length=1000)
    parameters = models.ManyToManyField(MeasurementParameter, related_name='measurement')

    def calc_all_tol_bands(self):

        for parameter in self.parameters.all():
            hi, lo = parameter.tolerance_band()

    def __str__(self):
        return self.name

所以在我看来,我尝试通过以下方式计算所有公差带:

product.calc_all_tol_bands()

但是,如果我尝试获取局部变量:

product.parameters.all()[0].tol_low

我一直都没有。

要在MeasurementParameter模型中设置计算值,我需要做什么?

约翰。

1 个答案:

答案 0 :(得分:1)

这是预期的行为。评估时

product.parameters.all()[0]

这意味着您进行数据库提取。因此,Django将获取这些参数中的第一个。由于tol_lowtol_high not 持久的(不存储在数据库中),因此这意味着它将退回到class属性None上。

这里的计算非常简单,因此我建议您将其转换为properties [Python-doc]

class MeasurementParameter(models.Model):    
    tolerance = models.FloatField()
    set_value = models.FloatField()

    @property
    def tol_low(self):
        return self.set_value * (100-self.tolerance)/100

    @property
    def tol_high(self):
        return self.set_value * (100+self.tolerance)/100

    def tolerance_band(self):
        return self.tol_high, self.tol_low

因此,在此我们将在必要时评估属性。这更可靠:如果更改对象的toleranceset_value,则该对象的tol_lowtol_high将有所不同。因此,没有可用的复杂代码来更新相关更新的值。 calc_all_bands也不是必需的,因为仅在需要时进行计算。

请注意,您不能在Django ORM过滤器等中使用属性。在这种情况下,您可以将该属性编码为查询表达式,并用这些注释注释queryset。