gpt4 book ai didi

python - WTForms 如何使用 DecimalField 在错误输入时生成正确的字段错误

转载 作者:行者123 更新时间:2023-12-01 05:48:17 24 4
gpt4 key购买 nike

看看这个例子

class MyForm(ForM):
...snip...
quantity = DecimalField(u'Quantity', [NumberRange(1, 8)])
...snip...

如果用户能够配合并输入可以强制为数字类型的内容,则效果会很好。但是,如果用户在浏览器中的该字段中输入:“asdf”,则 DecimalField抛出 Type Error当我尝试在浏览器中渲染它时。

这是回溯的相关部分:

Traceback (most recent call last):
File "/path/to/app/venv/local/lib/python2.7/site-packages/jinja2/environment.py", line 894, in render
return self.environment.handle_exception(exc_info, True)
File "/path/to/app/www/templates/submodule/user/submission.html", line 26, in block "submodule_content"
{{form.quantity}}
File "/path/to/app/venv/local/lib/python2.7/site-packages/wtforms/fields/core.py", line 139, in __call__
return self.widget(self, **kwargs)
File "/path/to/app/venv/local/lib/python2.7/site-packages/wtforms/widgets/core.py", line 123, in __call__
kwargs['value'] = field._value()
File "/path/to/app/venv/local/lib/python2.7/site-packages/wtforms/fields/core.py", line 542, in _value
return format % self.data
TypeError: a float is required

我希望字段本身添加一个错误,而不是这种行为,以便我仍然可以渲染 t。

我当前的解决方案涉及使用 TextField而不是DecimalField并提供IsNumeric验证器的调用方法如下:

def __call__(self, form, field):
if field.data:
try:
field.data = float(field.data)
except ValueError as e:
raise ValidationError(self.message)

这几乎完美地工作,并且是我当前的解决方案,但肯定必须有一种 wtforms 惯用的方法来做到这一点。

最佳答案

我不得不处理类似的问题。 SelectMultipleFieldcoerce=text_type (这是默认的 kwarg)将输入数据转换为 str/unicode 。这意味着它“强制”None (当用户未选择任何内容时输入到我的字段中的值)输入 "None" - 调试起来非常痛苦。您的问题清楚地表明,不仅仅是我参与了 wtforms 内部验证过程。

我发现的正确解决方案是,您编写 StringField 的自定义子类(文本字段)并覆盖 __call__ , process_data ,和process_formdata方法来满足您的需求。 __call__用于将它们渲染为 html(这应该由另一个 widget 可调用完成), process_data通常用于从 python 对象(这意味着服务器端)获取数据,并且 process_formdata就像 process_data除非它处理用户提交的表单。或者,如果您想要 DRY(不要重复),您可以覆盖 __init__并将您的自定义验证器设为默认值。

编辑:

DecimalField的愚蠢代码是导致 TypeError 的原因。看看它的_value()方法,由 DecimalField 使用的渲染小部件以获得 <input type="text" ... value=X> 的 X

def _value(self):
if self.raw_data:
return self.raw_data[0]
elif self.data is not None:
if self.places is not None: # <-- this line brings you the pain
if 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)
return text_type(quantized)
else:
# If for some reason, data is a float or int, then format
# as we would for floats using string formatting.
format = '%%0.%df' % self.places
return format % self.data
else:
return text_type(self.data)
else:
return ''

它检查 field.placesfield.data 类型之前-field.places在字段创建时声明,只是说您想要 N 位精度;它并不表明您有Decimal的N位数字作为您的fields.data ,但 wtforms 开发人员不知何故决定检查 field.places足以假设该字段包含相应的 float 。 (代码检查 quantize 上是否有 field.data 属性,但这仅适用于小数)

我认为你必须编写自己的 DecimalField 子类。这是我尝试编写 DecimalField 的非白痴版本:

from wtforms.fields.core import DecimalField as _DecimalField

class DecimalField(_DecimalField):
def _value(self):
try:
float(self.data) #check whether you have a 'number'
return super(DeciamlField, self)._value()
except (TypeError, ValueError): #self.data is 'None', 'asdf' ...
return text_type(self.data) if self.data else ''

关于python - WTForms 如何使用 DecimalField 在错误输入时生成正确的字段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15366452/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com