flask-wtf form validation not working for my new app

flask, flask-wtforms, python

Solution

You have a number of problems.

The most important is that validation occurs in the POST request view function. In your example this is function `sr`. That function should create the form object and validate it before adding stuff to the database.

Another problem in your code (assuming the above problem is fixed) is that after validate fails you redirect. The correct thing to do is to render the template right there without redirecting, because the error messages that resulted from validation are loaded in that form instance. If you redirect you lose the validation results.

Also, use `validate_on_submit` instead of `validate` as that saves you from having to check that `request.method == 'POST'`.

Example:

@app.route('/sr', methods=['POST'])    
def sr():
    form = subReddit()
    if not form.validate_on_submit():
        return render_template('index.html',form=form)
    g.db.execute("UPDATE subreddit SET sr=(?)", [form.subreddit.data])      
    return redirect(url_for('index'))

Additional suggestions:

- it is common practice to start your class names with an upper case character. `SubReddit` is better than `subReddit`.

- it is also common to have the GET and POST request handlers for a form based page in the same view function, because that keep the URLs clean when validation fails without having to jump through hoops to get redirects working. Instead of having the `sr` function separately you can just combine it with `index()` and have the action in the form go to `url_for('index')`.

Problem

I've used flask before and I've had working form validation, but for some reason it's not working for my new app. Here is the basic code of the form. ``` from flask.ext.wtf import Form, TextField, TextAreaField, SubmitField, validators,ValidationError class subReddit(Form): subreddit = TextField('subreddit', [validators.Required('enter valid subreddit')]) next = SubmitField('next') change = SubmitField('change') user = TextField('user', [validators.Required('enter valid user')]) fetch = SubmitField('fetch comments') ``` I have subreddit as the validation field, so if it's empty, I want it to throw an error and reload the page. The HTML: ``` <form class='sub' action="{{ url_for('sr') }}" method='post'> {{ form.hidden_tag() }} <p> if you want to enter more than one subreddit, use the + symbol, like this: funny+pics+cringepics <p> <br/> {% for error in form.subreddit.errors %} <p>{{error}}</p> {% endfor %} {{form.subreddit.label}} {{form.subreddit}} {{form.change}} </form> ``` I have CSRF_ENABLED=True in my routes.py as well. What am I missing? When I leave the subredditfield empty and click change, it just reloads the page, no errors. This is an issue because whatever is in the field will get recorded in my database, and it can't be empty. EDIT ``` @app.route('/index',methods=['GET','POST']) @app.route('/',methods=['GET','POST']) def index(): form = subReddit() rand = random.randint(0,99) sr = g.db.execute('select sr from subreddit') srr = sr.fetchone()[0] r = requests.get('http://www.reddit.com/r/{subreddit}.json?limit=100'.format(subreddit=srr)) j = json.loads(r.content) pic = j['data']['children'][rand]['data']['url'] title = None if form.validate_on_submit(): g.db.execute("UPDATE subreddit SET sr=(?)", [form.subreddit.data]) print 'validate ' if j['data']['children'][rand]['data']['url']: print 'pic real' sr = g.db.execute('select sr from subreddit') srr = sr.fetchone()[0] r = requests.get('http://www.reddit.com/r/{subreddit}.json?limit=100'.format(subreddit=srr)) pic = j['data']['children'][rand]['data']['url'] title = str(j['data']['children'][rand]['data']['title']).decode('utf-8') return render_template('index.html',form=form,srr=srr,pic=pic,title=title) else: print 'not valid pic' return render_template('index.html',form=form,srr=srr,pic=pic) else: print 'not valid submit' return render_template('index.html',form=form,srr=srr,pic=pic) return render_template('index.html',form=form,srr=srr,pic=pic) ```

Original source