WTForms中的十进制字段舍入

时间:2015-01-05 14:48:48

标签: python wtforms flask-wtforms

我有一个包含价格十进制字段的表单,如下所示:

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()])

当我提交表单时,小数值被舍入到小数点后两位,但这种情况从未发生过。我总是得到指定的值(例如99.853是99.853,而不是99.85)。

1 个答案:

答案 0 :(得分:3)

正如@mueslo正确推断的那样,这是因为默认的DecimalField实现并未完善它收到的表单数据。它只会舍入初始数据(如默认值模型/已保存数据)。

我们可以使用修改过的DecimalField实现轻松更改此行为,其中我们覆盖process_formdata方法。有点像:

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'))

使用示例:

rounding_field = BetterDecimalField(round_always=True)

Gist