I have the following model:
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
I wish to set the calculated local variables tol_low and tol_high using the tolerance_band method.
The model is has a ManyToMany relationship with another model called Product.
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
So in my view I attempt to calculate all tolerance bands by:
product.calc_all_tol_bands()
However if I try and get the local variables:
product.parameters.all()[0].tol_low
I get None all the time.
What do I need to do to be able to set calculated values in the MeasurementParameter model?
John.
This is expected behavior. When you evaluate
product.parameters.all()[0]
this means you make a database fetch. So Django will fetch the first of these parameters. Since the tol_low and tol_high are not persistent (not stored in the database), this means that it will fallback on the class attribute, which is None.
The calculations here, are rather simple, so I propose that you convert these to 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
Here we thus will evaluate the property when necessary. This is more robust: if you change the tolerance of an object, or the set_value, then the tol_low and tol_high will be different for that object. So there is no complex code in place to update the value for relevant updates. The calc_all_bands is not necessary either, since calculations are simply done when requested.
Note that you can not use properties in Django ORM filters, etc. In that case, you can encode the property as a query expression and annotate the queryset with these.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With