Reputation: 14556
In my model, percentage data is stored as fractional values in the 0.0-1.0 range. Because they are percentages, I want the user to view and edit the values in the 0.0-100.0 range.
What is the preferred way of transforming data between its stored value and the displayed value? Note that the format depends on another instance variable.
My model looks like this:
class MyModel(models.Model):
format = models.CharField(choices=(('percentage', 'Percentage'), ('absolute', 'Absolute'))
my_value = models.FloatField()
def _get_my_value_display(self):
if self.format == 'percentage':
return self.my_value * 100
else:
return self.my_value
def _set_my_value_display(self, v):
if self.format == 'percentage':
return v / 100
else:
return self.my_value
my_value_display = property(_get_my_value, _set_my_value)
In the form, I tried to use the display property as a form field, but that doesn't work (Unknown field(s) (my_value_display) specified for MyModel):
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ('my_value_display', )
Upvotes: 1
Views: 1288
Reputation: 4382
Personally, I'd probably try to create a django.forms.FloatField
subclass and a django.forms.TextInput
subclass, kind of like this:
class PercentageInput(TextInput):
def render(self, name, value, attrs=None):
try:
value = float(value)
value *= 100
except ValueError:
pass
return super(PercentageInput, self).render(name, value, attrs)
class PercentageField(FloatField):
widget = PercentageInput
def to_python(self, value):
value = super(PercentageField, self).to_python(value)
return value / 100
Then just define your ModelForm
this way:
class MyForm(forms.ModelForm):
my_value = PercentageField()
It might fail in a few corner cases, maybe also when the user supplies an invalid value, but the basic idea should be all right.
Upvotes: 5