The Optional validator allows for both empty values and if the value is not present (from the docs):
class wtforms.validators.Optional(strip_whitespace=True)
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.
I have some additional validators on a field, and I would like if those validators ran even if the input is an empty string. The builtin Optional
validator makes the rest of the validators skipped if the input was an empty string. Is there a built in or any other way to achieve this?
I am using this form to validate PUT
requests. Let's say I have User entities with username
s as ID and middlename
s as an optional field. Then the validator for the fields would look something like:
class UserUpdateForm(Form):
username = fields.StringField('username', [
validators.Optional(),
validators.Length(min=5, max=500)
])
middlename = fields.StringField('middlename', [
validators.Optional()
])
So I would allow for PUT
requests that does not have a username
or middlename
parameter, and those would leave the fields untouched. However, when the parameter is present and is an empty string, I would like the username
field validation fail because of the Length
validator, but I would allow the middlename
field to be set to the empty string.
From another perspective: I would like to distinguish non-present parameters and empty string parameters.
I took a look at the source of the Optional
validator:
class Optional(object):
...
def __call__(self, form, field):
if not field.raw_data or isinstance(field.raw_data[0], string_types) and not self.string_check(field.raw_data[0]):
field.errors[:] = []
raise StopValidation()
As you can see in and not self.string_check(field.raw_data[0])
, empty strings are explicitly considered here. I wonder what would happen if I sent two values like a=foo&a=&b=bar
.
Anyway, the quick solution for me was to implement a new validator:
class OptionalButNotEmpty(object):
"""
Allows missing but not empty input and stops the validation chain from continuing.
"""
# Code is a modified version of `Optional` (https://github.com/wtforms/wtforms/blob/master/wtforms/validators.py#L148)
field_flags = ('optional', )
def __call__(self, form, field):
if not field.raw_data:
raise wtforms.validators.StopValidation()