Flask应用提交目标="_ blank"仅在wtforms验证后才形成 [英] Flask app submit target="_blank" form only after wtforms validation

查看:32
本文介绍了Flask应用提交目标="_ blank"仅在wtforms验证后才形成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的Flask应用程序中,我有一个使用 wtforms jinja 模板生成的表单.如果通过验证,则我想在新选项卡中重定向,否则,我想停留在同一页面上并显示错误.但是,如果我在表单中设置 target ="_ blank" ,它将在不通过验证的情况下打开一个新选项卡,并在其中显示错误.删除 target ="_ blank" 不会打开新标签.有没有一种方法可以在不重写js中整个验证的情况下实现?谢谢!

代码:

从wtforms中的

 导入Form,TextAreaField,StringField,验证器类SubmitForm(Form):field1 = StringField(u'field1',[validators.DataRequired()])field2 = TextAreaField(u'field2',[validators.DataRequired()])@ app.route('/',Methods = ['POST'])def sub():表格= SubmitForm(request.form)如果request.method =='POST'和form.validate():# 巨大的成功返回重定向('/my_redirect_uri')返回render_template('index.html',form = form)@ app.route('/')def layout():返回render_template('index.html',form = SubmitForm()) 

index.html:

  {%from"_formhelpers.html" import render_field%}< form method =发布动作="/" target ="_ blank">< dl>{{render_field(form.field1)}}{{render_field(form.field2)}}</dl>< p><输入类型=提交值=提交></form> 

_formhelpers.html (无关紧要,但为了完整起见):

  {%宏render_field(field)%}< dt> {{field.label}}< dd> {{field(** kwargs)| safe}}{%,如果field.errors%}< ul class = errors>{%为field.errors%中的错误}< li> {{错误}}</li>{%endfor%}</ul>{% 万一 %}</dd>{%endmacro%} 

解决方案

主要问题

您必须传递 form 对象以及代表表单字段的变量,即 field1 field2 .

详细信息

上述内容意味着您需要更改:

返回重定向('/my_redirect_uri')

返回重定向('/my_redirect_uri',form = form,field1 = field1,field2 = field2)

这还意味着您必须调整视图方法:

  @ app.route('/',Methods = ['POST'])def sub():表格= SubmitForm(request.form)如果request.method =='POST'和form.validate():# 巨大的成功field1 = form.field1.datafield2 = form.field2.datareturn redirect('/my_redirect_uri',form = form,field1 = field1,field2 = field2)返回render_template('index.html',form = form) 

现在,您的程序有了一些改进:

  • 无代码原则:

if request.method =='POST'并替换为 if form.validate_on_submit():(保存一条指令)>

为了可扩展性,因为在将来的版本和程序的重新编辑中,任何更改使用 url_for()时,路由名称所生成的名称将自动可用,因为它会使用URL映射生成URL.您可以在 return redirect('/my_redirect_uri')中使用它(可以检查我提供的链接以获取更多信息)

  • 使用会话:

会话将使您的应用能够记忆"正在发送的表单数据.在您的示例中,您可以通过以下方式使用会话:

  session ['field1'] = form.field1.datasession ['field2'] = form.field2.data 

例如,这意味着上面的行:

  return redirect('/my_redirect_uri',form = form,field1 = field1,field2 = field2) 

必须更改为:

  return redirect('my_redirect_uri',form = form,session.get('field1'),session.get('field2')) 

请注意,如果要实现会话,则将需要设置一个秘密密钥,因为它们存储在客户端,因此需要对其进行保护(按照Flask的哲学进行加密).这意味着您必须以这种方式配置应用程序:

  app.config ['SECRET_KEY'] ='您自己的一些秘密短语' 

实际上,该问题与您打开的浏览器选项卡无关.整个问题源自 redirect()语句.

有关使用会话的好处的更多详细信息?检查下一部分:

有关重定向的字词:

您的POST请求由 redirect 处理,因此,当POST请求结束时,您将失去对表单数据的访问权限.

重定向语句只是一个响应,当收到该响应时,浏览器会发出GET请求.该机制主要用于以下(和类似的)情况:

如果您尝试刷新提交表单数据所用的同一浏览器窗口,则浏览器将提示您弹出窗口以确认您要再次发送数据,因为浏览器在设计上会记住上次执行的请求.当然,这对于您的应用程序用户来说是讨厌的.那里我们需要会议.这对于重定向到的浏览器选项卡也很有帮助.

In my Flask app I have a form generated with wtforms and jinja templates. If validation passes I want to redirect in a new tab, else I want to stay on the same page and display the errors. However if I set target="_blank" in my form, it opens a new tab without validation passing and shows the errors there. Removing target="_blank" will not open a new tab. Is there a way of achieving this without rewriting the whole validation in js? Thanks!

Code:

from wtforms import Form, TextAreaField, StringField, validators

class SubmitForm(Form):
    field1 = StringField(u'field1', [validators.DataRequired()])
    field2 = TextAreaField(u'field2', [validators.DataRequired()])

@app.route('/', methods=['POST'])
def sub():
    form = SubmitForm(request.form)
    if request.method == 'POST' and form.validate():
        # great success
        return redirect('/my_redirect_uri')
    return render_template('index.html', form=form)

@app.route('/')
def layout():
    return render_template('index.html', form=SubmitForm())

index.html:

{% from "_formhelpers.html" import render_field %}
<form method=post action="/" target="_blank">
  <dl>
    {{ render_field(form.field1) }}
    {{ render_field(form.field2) }}
  </dl>
  <p><input type=submit value=Submit>
</form>

_formhelpers.html(not that relevant but for the sake of completness):

{% macro render_field(field) %}
  <dt>{{ field.label }}
  <dd>{{ field(**kwargs)|safe }}
  {% if field.errors %}
    <ul class=errors>
    {% for error in field.errors %}
      <li>{{ error }}</li>
    {% endfor %}
    </ul>
  {% endif %}
  </dd>
{% endmacro %}

解决方案

Main issue

You must pass the form object as well as the variables representing your form fields namely field1 and field2.

Details

What is being stated above means that you need to change:

return redirect('/my_redirect_uri')

to

return redirect('/my_redirect_uri', form=form, field1=field1, field2=field2)

This also means that you have to adjustments to your view method:

@app.route('/', methods=['POST'])
def sub():
    form = SubmitForm(request.form)
    if request.method == 'POST' and form.validate():
        # great success
        field1 = form.field1.data
        field2 = form.field2.data
        return redirect('/my_redirect_uri', form=form, field1=field1, field2=field2)
    return render_template('index.html', form=form)

Now there are some improvements to your program:

  • Code less principle:

Replace if request.method == 'POST' and form.validate(): by if form.validate_on_submit(): (you save one instruction)

For the sake of scalability because in future versions and reedits of your program, any changes made to route names will be automatically available when using url_for() as it generates URLs using the URL map. You may use it in return redirect('/my_redirect_uri') (you may check the link I provided for further information)

  • Use sessions:

Sessions will make your application "able to remember" the form data being sent. In your example, you can use a session this way:

session['field1'] = form.field1.data
session['field2'] = form.field2.data

This means, for example, the above line:

return redirect('/my_redirect_uri', form=form, field1=field1, field2=field2)

must be changed to:

return redirect('my_redirect_uri', form=form, session.get('field1'), session.get('field2'))

Note that if you want to implement sessions, you will need to set a secret key because they are stored on the client side, so they need to be protected (cryptographically in Flask's philosophy). This mean you must configure your application this way:

app.config['SECRET_KEY'] = 'some secret phrase of your own'

Actually, the problem is not related to the browser tab you opened. The whole issue emanates from the redirect() statement.

More details on why it is good to use sessions? Check the next last section:

A word about redirect:

Your POST request is handled by redirect, consequently you loose access to the form data when the POST request ends.

The redirect statement is simply a response which, when received, the browser issues a GET request. This mechanism is there mainly for the following (and similar) situation:

If you try to refresh the same browser window on which you submitted the form data, the browser will prompt you a pop up window to confirm that you want to send the data (again) because the browser remembers, by design, the last request it performed. Of course, this is nasty for the user of your application. There we need sessions. This is also helpful for the browser tab to which you redirect.

这篇关于Flask应用提交目标="_ blank"仅在wtforms验证后才形成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆