WTForms: IntegerField skips coercion on string value
I have an instance Form
with one IntegerField
.
IntegerField renders HTML as <input>
with type="text"
, and the data is POSTed back from the HTML form as a text string. However, the form will not be validated if the posted data has a string value for an IntegerField (passed via a dict in the data parameter).
Here's an example of a toy:
from wtforms import validators, Form, IntegerField
class TestForm(Form):
num = IntegerField('How Many?', [validators.NumberRange(min=1, max=100)])
test_form1 = TestForm()
print("HTML Render 1: %s" % test_form1.num())
data_in = {'num': '66'} # Note '66' is a string as would be POSTed
test_form2 = TestForm(data=data_in)
print("HTML Render 2: %s" % test_form2.num())
print(" Validate: %s" % test_form2.validate())
print(" Errors: %s" % test_form2.errors)
Output:
HTML Render 1: <input id="num" name="num" type="text" value="">
HTML Render 2: <input id="num" name="num" type="text" value="66">
Validate: False
Errors: {'num': [u'Number must be between 1 and 100.']}
The docstring for IntegerField says:
IntegerField (field): a text field, except that all input is forced to be an integer
How can I force str
to int
that the form has been checked?
source to share
This is from one of the WTForms developers:
Fields only process form data, they do not copy object data, this allows people to use objects> "like int" and still work with them without the value being knocked down. It is your responsibility to pass the correct data types to the / kwargs objects.
And from the docs:
process_formdata (Valuelist) Process data received by wire from the form.
This will be called during form construction with the data passed through the formdata argument.
Parameter: valuelist - list of strings to process.
In your example, the method process_formdata
to IntegerField
be never called
You are passing in str
, and it won't be forced because you are supplying it as a keyword argument data
. The keyword parameter data
means exactly the data you want to check without being forced . Since '66'
there is still remains str
, validators do not skip it.
The keyword argument formdata
specifies the data coming from the wire. This will go through a process of compulsion . There is only one catch, it only takes MultiDict
as objects. If you look at the example below, I used webob MutliDict
, but there is also one in the Werkzeug library . If you close a regular python dictionary in MultiDict
and supply it as a keyword formdata
, your form will validate as expected.
from wtforms import validators, Form, IntegerField
from webob.multidict import MultiDict
class TestForm(Form):
num = IntegerField('How Many?', [validators.NumberRange(min=1, max=100)])
data_in = {'num': '66'} # Note '66' is a string as would be POSTed
test_form2 = TestForm(formdata=MultiDict(data_in))
print("HTML Render 2: %s" % test_form2.num())
print(" Validate: %s" % test_form2.validate())
print(" Errors: %s" % test_form2.errors)
HTML Render 2: <input id="num" name="num" type="text" value="66">
Validate: True
Errors: {}
source to share