pallets-eco/wtforms

SelectMultipleField should support choices specified as coercible values.

Closed this issue · 2 comments

Actual Behavior

>>> class DummyPostData(dict):
...     def getlist(self, key):
...             v = self[key]
...             if not isinstance(v, (list, tuple)):
...                     v = [v]
...             return v
...
>>> import wtforms
>>> class F(wtforms.Form):
...     foo=wtforms.SelectMultipleField(choices=[('1', 'One'), ('2', 'Two')], coerce=int)
...
>>> post_data = DummyPostData(foo=["1", "2"])
>>> form = F(post_data)
>>> form.validate()
False
>>> form.errors
{'foo': ["'1', '2' are not valid choices for this field."]}

Expected Behavior

The form should be valid when the post data is a valid option after coercing both post data and choices:

>>> class DummyPostData(dict):
...     def getlist(self, key):
...             v = self[key]
...             if not isinstance(v, (list, tuple)):
...                     v = [v]
...             return v
...
>>> import wtforms
>>> class F(wtforms.Form):
...     foo=wtforms.SelectMultipleField(choices=[('1', 'One'), ('2', 'Two')], coerce=int)
...
>>> post_data = DummyPostData(foo=["1", "2"])
>>> form = F(post_data)
>>> form.validate()
True

Environment

  • Python version: 3.9
  • wtforms version: 3.1.1

There is indeed a difference of behavior between SelectField and SelectMultipleField.

>>> import wtforms
>>> from werkzeug.datastructures import ImmutableMultiDict
>>> class F(wtforms.Form):
...     foo=wtforms.SelectMultipleField(choices=[('1', 'One'), ('2', 'Two')], coerce=int)
...     bar=wtforms.SelectField(choices=[('1', 'One'), ('2', 'Two')], coerce=int)
>>> form = F(ImmutableMultiDict({"foo": ["1"], "bar": ["1"]}))
>>> form.validate()
False
>>> form.errors
{'foo': ["'1' is not a valid choice for this field."]}

Fixed in version 3.1.2