diff --git a/CHANGES.rst b/CHANGES.rst index 62ebc1f74..5c99cde31 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,6 +6,8 @@ Version 3.x.x Unreleased - Display :class:`~wtforms.Flags` values in their repr. :pr:`808` +- :class:`~fields.SelectField` and :class:`~fields.SelectMultipleField` + ``choices`` can be `None` if `validate_choice` is `False` :pr:`809` Version 3.1.0 ------------- diff --git a/src/wtforms/fields/choices.py b/src/wtforms/fields/choices.py index 3ceabb182..4eb868969 100644 --- a/src/wtforms/fields/choices.py +++ b/src/wtforms/fields/choices.py @@ -135,12 +135,12 @@ def process_formdata(self, valuelist): raise ValueError(self.gettext("Invalid Choice: could not coerce.")) from exc def pre_validate(self, form): - if self.choices is None: - raise TypeError(self.gettext("Choices cannot be None.")) - if not self.validate_choice: return + if self.choices is None: + raise TypeError(self.gettext("Choices cannot be None.")) + for _, _, match, _ in self.iter_choices(): if match: break @@ -189,12 +189,12 @@ def process_formdata(self, valuelist): ) from exc def pre_validate(self, form): - if self.choices is None: - raise TypeError(self.gettext("Choices cannot be None.")) - if not self.validate_choice or not self.data: return + 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] diff --git a/tests/fields/test_select.py b/tests/fields/test_select.py index 82db6f0b0..aa5874af5 100644 --- a/tests/fields/test_select.py +++ b/tests/fields/test_select.py @@ -132,6 +132,12 @@ def test_dont_validate_choices(): assert len(form.a.errors) == 0 +def test_choices_can_be_none_when_choice_validation_is_disabled(): + F = make_form(a=SelectField(validate_choice=False)) + form = F(DummyPostData(a="b")) + assert form.validate() + + def test_choice_shortcut(): F = make_form(a=SelectField(choices=["foo", "bar"], validate_choice=False)) form = F(a="bar") diff --git a/tests/fields/test_selectmultiple.py b/tests/fields/test_selectmultiple.py index 426c36b25..5fd2a99b7 100644 --- a/tests/fields/test_selectmultiple.py +++ b/tests/fields/test_selectmultiple.py @@ -107,6 +107,12 @@ def test_dont_validate_choices(): assert len(form.a.errors) == 0 +def test_choices_can_be_none_when_choice_validation_is_disabled(): + F = make_form(a=SelectMultipleField(validate_choice=False)) + form = F(DummyPostData(a="b")) + assert form.validate() + + def test_requried_flag(): F = make_form( c=SelectMultipleField(