pallets-eco/wtforms

Validator order isn't immediately apparent

Opened this issue · 0 comments

I was trying to understand why validators placed on the field wouldn't be validated prior to in-line validators, and came up with this (albeit impossible) scenario to demonstrate the problem.

Actual Behavior

In this example, the StringField validator isn't being called at all, as shown in f.errors:

>>> from webob.multidict import MultiDict
>>> from wtforms import Form, StringField
>>> from wtforms.validators import ValidationError, Length
>>>
>>> class F(Form):
...     name = StringField(validators=[Length(min=50)])
...     def validate_name(form, field):
...         if len(field.data) > 50:
...             raise ValidationError("Name must be less than 50 characters")
...
>>> f = F(MultiDict([("name", "a" * 51)]))
>>>
>>> assert not f.validate()
>>> assert f.errors == {"name": ["Name must be less than 50 characters"]}

Expected Behavior

In this example, I flip the input condition to a shorter string, and expect that the Length validator tell me that it's not long enough before calling validate_name().

>>> from webob.multidict import MultiDict
>>> from wtforms import Form, StringField
>>> from wtforms.validators import ValidationError, Length
>>>
>>> class F(Form):
...     name = StringField(validators=[Length(min=50)])
...     def validate_name(form, field):
...         if len(field.data) > 50:
...             raise ValidationError("Name must be less than 50 characters")
...
>>> f = F(MultiDict([("name", "a")]))
>>>
>>> assert not f.validate()
>>> assert f.errors == {"name": ["Field must be at least 50 characters long."]}

In my head, the field validation should happen before a form's in-line field validation, but had trouble finding the order expressed in the documentation.

Environment

  • Python version: 3.12.4
  • wtforms version: 3.1.2