2016-11-26 2 views
2

В моем приложении Flask У меня есть форму, сгенерированную с помощью wtforms и jinja. Если проверка прошла, я хочу перенаправить на новую вкладку, иначе я хочу остаться на одной странице и отобразить ошибки. Однако, если я установил target="_blank" в моей форме, он откроет новую вкладку без прохождения проверки и покажет там ошибки. Удаление target="_blank" не откроет новую вкладку. Есть ли способ достичь этого, не переписывая всю проверку в js? Благодаря!Flask app submit target = "_ blank" form only after wtforms validation

Код:

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 (не то, что отношение, но ради Комплектность):

{% 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, а также переменные, представляющие поля формы, а именно: field1 и field2.

Детали

То, что было сказано выше означает, что вам нужно изменить:

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

Обратите внимание, что если вы хотите реализовать сеансы, вам нужно будет установить секретный ключ, потому что они хранятся на стороне клиента, поэтому их необходимо защитить (криптографически в философии Флакла). Это означает, что вы должны настроить приложение таким образом:

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

На самом деле, проблема не связана с вкладки браузера вы открыли. Весь вопрос исходит из заявления redirect().

Подробнее о том, почему хорошо использовать сеансы? Проверьте следующий последний раздел:

Несколько слов о перенаправлении:

Ваш запрос на POST обрабатывается redirect, следовательно, вы потеряете доступ к форме данных, когда запрос POST заканчивается.

Оператор перенаправления - это просто ответ, который при получении браузера выдает запрос GET. Этот механизм существует в основном для следующей (и аналогичной) ситуации:

Если вы попытаетесь обновить то же окно браузера, на котором вы отправили данные формы, браузер предложит вам всплывающее окно, чтобы подтвердить, что вы хотите отправьте данные (снова), потому что браузер помнит, по дизайну, последний запрос, который он выполнил. Конечно, это неприятно для пользователя вашего приложения. Там нам нужны сеансы. Это также полезно для вкладки браузера, на которую вы перенаправляете.