pallets-eco / wtforms

A flexible forms validation and rendering library for Python.
https://wtforms.readthedocs.io
BSD 3-Clause "New" or "Revised" License
1.51k stars 395 forks source link

IntegerFiled property can not pass the InputRequired or DataRequired validator when it is 0 #819

Closed tingruizhang closed 9 months ago

tingruizhang commented 11 months ago

wtforms : 3.1.11

my IntegerField property:

status = IntegerField(validators=[DataRequired(message="please enter the account status")])

or

status = IntegerField(validators=[InputRequired(message="please enter the account status")])

both can not pass the validator DataRequired or InputRequired when status = 0

I overwrite the DataRequired's call method to

    def __call__(self, form, field):
        if field.data is None or isinstance(field.data, str) and not field.data.strip():
            if self.message is None:
                message = field.gettext('This field is required.')
            else:
                message = self.message
            field.errors[:] = []
            raise StopValidation(message)

use filed.data is None to deal with the condition : IntegerFiled data is 0 .

I want to learn more from you. Thanks

azmeuk commented 9 months ago

Can you provide a snippet demonstrating the bug you are referring to?

Here you can see that InputRequired passes the validation when the in put is 0.

>>> from werkzeug.datastructures import ImmutableMultiDict
>>> import wtforms
>>> class Form(wtforms.Form):
...     status1 = wtforms.IntegerField(validators=[wtforms.validators.DataRequired()])
...     status2 = wtforms.IntegerField(validators=[wtforms.validators.InputRequired()])
>>> f = Form(ImmutableMultiDict({"status1": "0", "status2": "0"}))
>>> f.validate()
False
>>> f.errors
{'status1': ['please enter the account status']}

The documentation explains this behavior:

Note there is a distinction between this and DataRequired in that InputRequired looks that form-input data was provided, and DataRequired looks at the post-coercion data. This means that this validator only checks whether non-empty data was sent, not whether non-empty data was coerced from that data. Initially populated data is not considered sent.