【问题标题】:How to redirect while keeping form data using Flask and WTForms?如何在使用 Flask 和 WTForms 保留表单数据的同时进行重定向?
【发布时间】:2019-11-16 04:32:40
【问题描述】:

让我们有一个带有注册表单的页面。它在#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'

函数如下所示:

@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)

【问题讨论】:

    标签: python flask redirect single-page-application


    【解决方案1】:

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

    要解决您的问题,您需要使用 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()
    

    当你运行服务器时,你会得到:

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

    【讨论】:

    • 如果我删除它,页面将显示而没有被模板化。 (我会丢失form 对象)
    • 我正在使用Flask-WTForms。该表单包含来自验证器的自己的错误消息。我想使用这些消息。
    • 使用闪存将表单数据保存到会话中,然后通过提供formdata 参数(如PhotoForm(CombinedMultiDict((request.files, request.form))))使用这些值重新创建表单,如下所述flask-wtf.readthedocs.io/en/stable/…
    • 是的,现在它可以正确重定向。但是,如果您添加用于显示消息的模板,它们不会显示 ``` {% for error in form.name.errors %} {{ error }} {% endfor %} ``
    • 在重新创建 form.validate() 后添加它可以解决问题,我已经编辑了我的答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-26
    • 1970-01-01
    • 2016-04-29
    • 2013-06-19
    • 1970-01-01
    相关资源
    最近更新 更多