Skip to content

Optional doesn't check field.data #842

@antonstakhouski

Description

@antonstakhouski

If the form was filled with an object (like in REST scenario), Optional validator always raises StopValidation because it checks field.raw_data (and not the field.data) which will be always empty.

from wtforms import Form
from wtforms.fields import StringField, FieldList
from wtforms.validators import IPAddress, Optional


class EditForm(Form):
    allow_list = FieldList(StringField(validators=[IPAddress(), Optional()]))


allow_list = ['555.555.555.555']


if __name__ == '__main__':
    form = EditForm()
    form.allow_list.process(None, allow_list)
    form.validate()
    print(form.errors)

Actual Behavior

> {}

Expected Behavior

> {'allow_list': [['Invalid IP address.']]}

Possible fix

class Optional:
    """
    Allows empty input and stops the validation chain from continuing.

    If input is empty, also removes prior errors (such as processing errors)
    from the field.

    :param strip_whitespace:
        If True (the default) also stop the validation chain on input which
        consists of only whitespace.

    Sets the `optional` attribute on widgets.
    """

    def __init__(self, strip_whitespace=True):
        if strip_whitespace:
            self.string_check = lambda s: s.strip()
        else:
            self.string_check = lambda s: s

        self.field_flags = {"optional": True}

    def __call__(self, form, field):
        if (
            not field.data
            or isinstance(field.data, str)
            and not self.string_check(field.data)
        ):
            field.errors[:] = []
            raise StopValidation()

If field.raw_data will be replaced with field.data, validation works as expected. But I don't know if this fix will break something in other places.

Environment

  • Python version: 3.10.13
  • wtforms version: 3.0.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions