2016-11-26 42 views
2

在我的Flask應用程序中,我有一個用wtformsjinja模板生成的表單。如果驗證通過,我想在新選項卡中重定向,否則我想保留在同一頁面上並顯示錯誤。但是,如果我在表單中設置了target="_blank",它將打開一個新選項卡,但不傳遞驗證並顯示那裏的錯誤。刪除target="_blank"將不會打開新的選項卡。有沒有一種方法可以在不重寫js中的整個驗證的情況下實現呢?謝謝!Flask app只有在wtforms驗證後提交target =「_ blank」表單

代碼:

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(不是相關但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 %} 
+0

我想你是對的。您需要編寫一個驗證您的Ajax請求的簡單控制器,然後您可以打開新的選項卡, –

回答

2

主要問題

您必須通過form對象以及表示您的表單域的變量,即field1field2

詳細

什麼被上述意味着你需要改變:

return redirect('/my_redirect_uri')

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

這也意味着,你必須調整你查看方法:

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

現在有你的程序了一些改進:

  • 代碼少的原則:

更換if request.method == 'POST' and form.validate():if form.validate_on_submit():(您節省一個指令)

爲了scalability的緣故,因爲在您的程序的將來版本和重新編輯中,使用url_for()時,路由名稱所做的任何更改都會自動提供,因爲它會使用URL映射生成URL。您可以在return redirect('/my_redirect_uri')使用它(你可以檢查我提供更多信息的鏈接)

  • 使用會話:

會議將讓您的應用程序「能夠記住」發送表單數據。在你的榜樣,你可以使用一個會話是這樣的:

session['field1'] = form.field1.data 
session['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'] = 'some secret phrase of your own' 

其實,這個問題是沒有關係的,你打開瀏覽器選項卡。整個問題發自redirect()聲明。

關於爲什麼使用會話很好的更多細節?檢查下最後一節:

字約重定向:

你的POST請求被redirect處理,因此你鬆訪問表單數據的POST請求結束時。

重定向語句只是一個響應,當接收到瀏覽器發出的GET請求時。此機制主要針對以下(和類似情況):

如果您嘗試刷新提交表單數據的同一個瀏覽器窗口,瀏覽器會提示您彈出一個窗口以確認您想要發送數據(再次),因爲瀏覽器通過設計記得它執行的最後一個請求。當然,這對於你的應用程序的用戶來說是討厭的。我們需要會議。這對您重定向到的瀏覽器選項卡也有幫助。