Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IntegerField not validating on empty string

I found that IntegerField does not validate when empty. To reproduce, copy the following block:

from flask import Flask, render_template_string
from flask_wtf import FlaskForm
from wtforms import IntegerField

app = Flask(__name__)
app.config['WTF_CSRF_ENABLED'] = False

class DemoForm(FlaskForm):
    demofield = IntegerField('demofield')

@app.route('/', methods=("GET","POST"))
def index():
    form = DemoForm()
    if form.validate_on_submit():
        return ("The form validated!")
    return render_template_string("<!DOCTYPE HTML> This is my form! <form method=\"post\">{% for field in form %}{{field}}{% endfor %}<input type=\"submit\">", form=form)

app.run(debug=True)

and save it in its own directory as app.py. Then open a terminal, cd to the directory, and run the following:

virtualenv flask
source flask/bin/activate
pip install flask flask-wtf
export FLASK_APP=app.py
python3 app.py

Connect to localhost:5000 in a web browser. Typing an integer into the form field and submitting will display "The form validated!" Typing something that is not an integer into the field, or leaving the field blank, and submitting just reloads the page. This does make some sense, since "" cannot be coerced into an integer.

I want to let my IntegerField be empty. I think the solution is to subclass IntegerField and override pre_validate() or post_validate(). I have:

class OptionalIntegerField(IntegerField):
    def post_validate(self, form, validation_stopped):
        print("post_validate is being called")
        if (self.data in (None, "")):
            return True

My question is:

  • is subclassing and overriding the correct solution?
  • if so, do I override pre_validate(), post_validate(), or both, and how? Do I need to return True inside them?
like image 510
qxu21 Avatar asked Oct 20 '25 12:10

qxu21


1 Answers

The Optional validator allows empty entries on form fields.

>>> from webob.multidict import MultiDict

>>> class F(Form):
...     foo = IntegerField(validators=[validators.Optional()])

>>> f = F(formdata=MultiDict(foo=1))
>>> f.validate()
True
>>> f = F(formdata=MultiDict(foo=''))
>>> f.validate()
True
>>> f = F(formdata=MultiDict(foo='a'))
>>> f.validate()
False

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.

like image 163
snakecharmerb Avatar answered Oct 23 '25 09:10

snakecharmerb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!