Skip to content

Commit

Permalink
Merge pull request #823 from azmeuk/issue-822-selectmultiplefield-coerce
Browse files Browse the repository at this point in the history
Fixes SelectMultipleField value coercion on validation.
  • Loading branch information
azmeuk authored Jan 6, 2024
2 parents 432cba6 + f1a3dc1 commit c53d557
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 6 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
.. currentmodule:: wtforms

Unreleased
----------

- Fix :class:`~fields.SelectMultipleField` value coercion on validation.
:issue:`822` :pr:`823`

Version 3.1.1
-------------

Expand Down
15 changes: 9 additions & 6 deletions src/wtforms/fields/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ def _choices_generator(self, choices):
_choices = zip(choices, choices)

for value, label, *other_args in _choices:
selected = self.coerce(value) == self.data
render_kw = other_args[0] if len(other_args) else {}
yield (value, label, self.coerce(value) == self.data, render_kw)
yield (value, label, selected, render_kw)

def process_data(self, value):
try:
Expand Down Expand Up @@ -173,9 +174,9 @@ def _choices_generator(self, choices):
else:
_choices = zip(choices, choices)

for value, label, *args in _choices:
for value, label, *other_args in _choices:
selected = self.data is not None and self.coerce(value) in self.data
render_kw = args[0] if len(args) else {}
render_kw = other_args[0] if len(other_args) else {}
yield (value, label, selected, render_kw)

def process_data(self, value):
Expand All @@ -201,9 +202,11 @@ def pre_validate(self, form):
if self.choices is None:
raise TypeError(self.gettext("Choices cannot be None."))

acceptable = {c[0] for c in self.iter_choices()}
if any(d not in acceptable for d in self.data):
unacceptable = [str(d) for d in set(self.data) - acceptable]
acceptable = [self.coerce(choice[0]) for choice in self.iter_choices()]
if any(data not in acceptable for data in self.data):
unacceptable = [
str(data) for data in set(self.data) if data not in acceptable
]
raise ValidationError(
self.ngettext(
"'%(value)s' is not a valid choice for this field.",
Expand Down
13 changes: 13 additions & 0 deletions tests/fields/test_selectmultiple.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,16 @@ def test_optgroup_option_render_kw():
assert list(form.a.iter_choices()) == [
("a", "Foo", True, {"title": "foobar", "data-foo": "bar"})
]


def test_can_supply_coercable_values_as_options():
F = make_form(
a=SelectMultipleField(
choices=[("1", "One"), ("2", "Two")],
coerce=int,
)
)
post_data = DummyPostData(a=["1", "2"])
form = F(post_data)
assert form.validate()
assert form.a.data == [1, 2]

0 comments on commit c53d557

Please sign in to comment.