如何在使用 Flask 和 WTForms 保留表单数据的同时重定向?

mat*_*usf 4 python redirect flask single-page-application

让我们有一个页面,上面有一个注册表单。它在第#registration. 如果用户提交无效数据,页面应该将他返回到该#registration部分并显示哪些字段提交了无效值。

我试图呈现模板并做出响应并重定向到它,但我得到了一个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'

Run Code Online (Sandbox Code Playgroud)

该函数如下所示:

  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'

Run Code Online (Sandbox Code Playgroud)

abd*_*sco 6

您不能发送带有redirect响应的内容,您只能说“转到此网址”。此外,flask 接受一个Response类,而不是一个实例作为redirect.

要解决您的问题,您需要使用 a session(或简单地flashing)来跨请求保留状态。

这是一个原型:

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()
Run Code Online (Sandbox Code Playgroud)

当你运行服务器时,你会得到:
在此处输入图片说明

提交无效表单后,您将被重定向到/#invalid并按预期填充表单:

无效提交