I have a form that contains a price decimal field, like so:
from flask.ext.wtf import Form
import wtforms
from wtforms.validators import DataRequired
from decimal import ROUND_HALF_UP
class AddListingBase(Form):
title = wtforms.StringField(validators=[DataRequired()])
details = wtforms.TextAreaField(validators=[DataRequired()])
price = wtforms.DecimalField(places=2, rounding=ROUND_HALF_UP, validators=[DataRequired()])
When I submit the form, the decimal value is suppoosed to be rounded to 2 decimal places, but that never happens. I always get the value as it was specified (e.g. 99.853 is 99.853, not 99.85 as it should be).
As @mueslo has rightly inferred, this is because the default DecimalField
implementation does not round off the form data it receives. It only rounds off the initial data (as in defaults, or model/saved data).
We can easily change this behavior with a modified DecimalField implementation, wherein we override the process_formdata
method. Somewhat like so:
from wtforms import DecimalField
class BetterDecimalField(DecimalField):
"""
Very similar to WTForms DecimalField, except with the option of rounding
the data always.
"""
def __init__(self, label=None, validators=None, places=2, rounding=None,
round_always=False, **kwargs):
super(BetterDecimalField, self).__init__(
label=label, validators=validators, places=places, rounding=
rounding, **kwargs)
self.round_always = round_always
def process_formdata(self, valuelist):
if valuelist:
try:
self.data = decimal.Decimal(valuelist[0])
if self.round_always and hasattr(self.data, 'quantize'):
exp = decimal.Decimal('.1') ** self.places
if self.rounding is None:
quantized = self.data.quantize(exp)
else:
quantized = self.data.quantize(
exp, rounding=self.rounding)
self.data = quantized
except (decimal.InvalidOperation, ValueError):
self.data = None
raise ValueError(self.gettext('Not a valid decimal value'))
Example usage:
rounding_field = BetterDecimalField(round_always=True)
Gist
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