web-dev-qa-db-ja.com

Flask-WTF-validate_on_submit()は決して実行されません

私はFlask-WTFを使用しています:

これが私のフォームです:

from flask.ext.wtf import Form, TextField

class BookNewForm(Form):
    name = TextField('Name')

これがコントローラです:

@book.route('/book/new', methods=['GET', 'POST'])
def customers_new():
    form = BookNewForm()
    if form.is_submitted():
        print "submitted"
    if form.validate():
        print "valid"
    if form.validate_on_submit():
        flash("Successfully created a new book")
        return redirect(url_for('.books_show'))
    return render_template('views/books_new.html', form=form)

ここで問題は、私の印刷ステートメントを見ると、常に送信されて印刷されますが、決して有効なものは印刷されず、validate_on_submit()が実行されないことです。どうして?

31
kadrian

HTMLフォームにCSRFフィールドを挿入していません。

_<form method=post>
    {{ form.csrf_token }}
    {{ form.name }}
    <input type=submit>
</form>
_

テンプレートに_form.csrf_token_を追加した後( docs )、フォームは期待どおりに検証されます。

フォームを検証した後にprint(form.errors)を追加して、発生したエラーを確認します。 errorsは検証前は空です。この場合、欠落に関するエラーがあります

_@book.route('/book/new_no_csrf', methods=['GET', 'POST'])
def customers_new_no_csrf():
    form = BookNewForm()
    print(form.errors)

    if form.is_submitted():
        print "submitted"

    if form.validate():
        print "valid"

    print(form.errors)

    if form.validate_on_submit():
        flash("Successfully created a new book")
        return redirect(url_for('.books_show'))

    return render_template('books_new.html', form=form)
_
_{}
submitted
{'csrf_token': [u'CSRF token missing']}
127.0.0.1 - - [29/May/2012 02:01:08] "POST /book/new_no_csrf HTTP/1.1" 200 -
127.0.0.1 - - [29/May/2012 02:01:08] "GET /favicon.ico HTTP/1.1" 404 -
_

GitHubで例を作成しました。

46
A.Ford

エラーを印刷できます

print form.errors

または

app.logger.debug(form.errors)

また、csrf-errorが発生した場合は、テンプレートにform.csrf_tokenを設定する必要があります。

12
kzfm

これをテンプレートhtmlファイルのタグの後に挿入します。

 {{ form.csrf_token }} 
2
lihuanshuai

テンプレートでFormFieldFieldListに対して反復処理しようとすると、これに遭遇しました。 2つのhidden_​​tag要素を1つはFieldListフォーム用に、もう1つはFieldFormフォーム用に埋め込む必要がありました。テンプレートのコメントでキーワード「非表示タグ」を検索してください

class ParamRangeForm( FlaskForm ):
    minX = FloatField( )
    maxX = FloatField( )

class ParamRangesForm( FlaskForm ):
    paramRanges = FieldList( FormField( ParamRangeForm ) )
    submit      = SubmitField( 'Submit' )

    def loadParams( self ) :
        for paramName in ["p1" , "p2" , "p3", "p4"] :
            prf = ParamRangeForm( )
            prf.minX = -100.9#float('-inf')
            prf.maxX = 100.5#float('-inf')
            self.paramRanges.append_entry( prf )

...

  <form action="" method="POST" enctype="multipart/form-data">
    {{ rangesForm.hidden_tag() }} <!--#### HIDDEN TAG #1 -->
    <table>
      <!--Print Column Headers-->
      <thead>
      <tr>
        <th class="ColumnHeader">Parameter</td>
        <th class="ColumnHeader">Min</td>
        <th class="ColumnHeader">Max</td>
      </tr>
      </thead>

      <!--Print Parameter Rows-->
      <tbody>
      {% for paramRange in rangesForm.paramRanges %}
        <tr>
          {{ paramRange.hidden_tag() }} <!--#### HIDDEN TAG #2 -->
          <td>p{{ loop.index }}</td>
          <td>{{ paramRange.minX }}</td>
          <td>{{ paramRange.maxX }}</td>
        </tr>
      {% endfor %}
      </tbody>
    </table>
    </div>
    {{ rangesForm.submit() }}
  </form>
1
jxramos

すべてのリクエストの前にログインしていなかった場合、flaskセッションをクリアしていました。これがこの問題の原因でした。

@main.before_request
def before_request():
    if not current_user.is_authenticated():
        # TODO clean sessions may cause CSRF missing issue
        session.clear()
        print "Session Cleared"
        return redirect(url_for('auth.login'))
1
tourdownunder

Flask-WTFでの検証問題のデバッグに数時間を費やしました。他の多くの問題と同様に、CSRF検証の問題でした。しかし、私のものは私が見つけた一般的な問題のいずれかによって引き起こされたのではありません。

CSRFの標準のFlask-WTF実装では、ブラウザにtwoを配信する必要があります。

One:非表示のCSRFフォームフィールド。

_<input id="csrf_token" name="csrf_token" type="hidden" value="ImYzODdmZTdhYTRlMmNkYWRjYmRlYWFmZjQxMDllZTQ1OWZmYzg3MTki.XKvOPg.gUCkF9j-vg0PrL2PRH-v43GeHu0">
_

2:セッションCookie HTTP応答ヘッダー。

_Set-Cookie: session=eyJjc3JmX3Rva2VuIjoiZjM4N2ZlN2FhNGUyY2RhZGNiZGVhYWZmNDEwOWVlNDU5ZmZjODcxOSJ9.XKvOPg.a3-W62MHvaGVkv2GYCi-dgpLE3Y; HttpOnly; Path=/
_

これらのいずれかがない場合、ブラウザは適切なCSRF検証の送信に失敗します。もちろん、これによりフォームの検証が失敗します。

_csrf_token_非表示フィールドがフォームに存在するが、セッションCookieが欠落している場合、フォームが送信されると次の応答を受け取ります...

_Bad Request
The CSRF session token is missing.
_

私の場合、コードのバグのため、セッションCookieがありませんでした。 Flaskサイト全体にカスタムHTTPヘッダーを提供する必要がありました。このように含めました...

_class LocalFlask(Flask):

    def process_response(self, response):
        response.headers['my-header'] = 'My Header Value'
        return response

app = LocalFlask(__name__)
_

ただし、これにより、_Flask.response.headers_メソッドに依存するものはすべて失敗します。それらの1つは、セッションCookie HTTPヘッダーを設定するFlaks-WTFです。

これは、LocalFlaskクラスからメソッドを継承するようにFlaskクラスにsuper()メソッドを追加することで解決できます。

_class LocalFlask(Flask):

    def process_response(self, response):
        response.headers['my-header'] = 'My Header Value'
        #LocalFlask inherits methods from Flask
        super(LocalFlask, self).process_response(response)
        return response

app = LocalFlask(__name__)
_
0
D. Morell

APIが変更されたと思います。変更してみてください

from flask.ext.wtf import Form

に:

from flask_wtf import Form
0
Kanav Anand