Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to redirect while keeping form data using Flask and WTForms?

Let's have a page with a registration form on it. It's in section #registration. If user submits invalid data, the page should return him back to the #registration section and display to which fields were submitted invalid values.

I tried to render template and make response and redirect to it but I'm getting a TypeError:

  File ".../app/routes.py", line 28, in index
    return redirect(url_for('.index', form=form, _anchor='registration'), 302, response)
  File ".../python3.7/site-packages/werkzeug/utils.py", line 507, in redirect
    mimetype="text/html",
TypeError: __call__() got an unexpected keyword argument 'mimetype'

The function looks like this:

@app.route('/', methods=['GET', 'POST'])
def index():
    form = RegisterForm()
    if form.validate_on_submit():
        # everithing OK
        return redirect(url_for('.index', _anchor='registration'))

    # If form was submitted but contained invalid information
    if form.is_submitted():
        response = make_response(render_template('index.html', form=form))
        return redirect(url_for('.index', _anchor='registration'), 302, response)

    return render_template('index.html', form=form)
like image 241
matusf Avatar asked Jul 05 '19 14:07

matusf


People also ask

How do I stay on the same page after submitting a Flask?

In order to stay on the same page on submit you can leave action empty ( action=”” ) into the form tag, or leave it out altogether.

How do you redirect a Flask route?

Another method you can use when performing redirects in Flask is the url_for() function. The way that url_for() works is instead of redirecting based on the string representation of a route, you provide the function name of the route you want to redirect to.

How do I make a redirect button Flask?

If you want your form to submit to a different route you can simply do <form action="{{ url_for('app. login') }}"> . If you just want to put a link to the page use the <a> tag. If you want to process the request and then redirect, just use the redirect function provided by flask.


1 Answers

You can't send content with a redirect response, you can only say "go to this url". Also flask accepts a Response class, not an instance as a parameter for redirect.

To solve your problem, you need to use a session (or simply flashing) to preserve state across requests.

Here's a prototype:

from flask import Flask, render_template_string, request, session, redirect
from werkzeug import MultiDict

from flask_wtf import FlaskForm
from wtforms import StringField, IntegerField
from wtforms.validators import AnyOf

app = Flask(__name__)
app.secret_key = 'secret'

class MyForm(FlaskForm):
    name = StringField('name', validators=[AnyOf(['secretname'])])

@app.route('/', methods=['POST', 'GET'])
def form_page():
    form = MyForm()
    html = '''
    {% for error in form.name.errors %} <span>{{ error }}</span> {% endfor %}
    <form method="POST" action="/">
        {{ form.csrf_token }}
        {{ form.name.label }} {{ form.name(size=20) }}
        <input type="submit" value="Go">
    </form>
    '''
    
    if request.method == 'GET':
        formdata = session.get('formdata', None)
        if formdata:
            form = MyForm(MultiDict(formdata))
            form.validate()
            session.pop('formdata')
        return render_template_string(html, form=form)
    
    if form.validate_on_submit():
        # use the form somehow
        # ...
        return redirect('/#registered')

    if form.is_submitted() and not form.validate():
        session['formdata'] = request.form
        return redirect('/#invalid')

if __name__ == "__main__":
    app.run()

When you run the server, you get:
enter image description here

After you submit an invalid form, you get redirected to /#invalid and form is populated as you'd expect:

invalid submission

  • http://flask.pocoo.org/docs/1.0/quickstart/#sessions
  • http://flask.pocoo.org/docs/1.0/patterns/flashing/#message-flashing-pattern
  • http://flask.pocoo.org/docs/1.0/api/#flask.redirect
like image 113
abdusco Avatar answered Oct 10 '22 14:10

abdusco