I have a Modelform that contains multiple DecimalFields with decimal_places=4. I need 4 decimal places as that is a reflection of the underlying data. This is a financial utility where mean values might consume all 4 decimal places. Users should be allowed to enter up to 4 decimal places, and forms should be displayed with up to 4 decimal places. I am not looking for any sort of rounding or truncation.
What I want to do is limit the display of trailing 0s in modelforms being rendered in my template, up to a minimum of 2 trailing 0s, as these are dollars. For instance:
3.1234 would still remain as 3.1234
3.1230 would become 3.123
3.1200 would become 3.12
3.1000 would become 3.10
3.0000 would become 3.00
I have came up with the following inside my modelforms init method:
def __init__(self, *args, **kwargs):
if self.initial:
for field_name, field in self.fields.items():
if isinstance(field, forms.DecimalField) and field.decimal_places == 4 and self.initial.get(field_name):
self.initial[field_name] = self.initial[field_name].normalize()
Using the .normalize()
drops ALL the trailing 0s (3.0000 -> 3), however, I want a minimum of 2. I thought of using .quantize()
, to enforce a minimum of 2 decimal places, but this rounds values with more then 2 decimal places, which I do not want. I don't think I can use template filters, as I would need to render the form values separately. I am rendering my form fields as {{ form.fieldname }}
.
If anyone can think of a solution for this, it would be much appreciated. <3
I ended up writing my own widget and applying it to the applicable fields in my form. Hope this helps if anyone else was experiencing this.
class DollarDisplayTextInput(forms.TextInput):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def format_value(self, value):
if value is not None and isinstance(value, Decimal):
#Strip trailing 0s, leaving a minimum of 2 decimal places
while (abs(value.as_tuple().exponent) > 2 and value.as_tuple().digits[-1] == 0):
value = Decimal(str(value)[:-1])
return value