web-dev-qa-db-ja.com

Flask --wtforms:検証は常にfalse

まず、pythonとFlaskに慣れていないので、質問がばかげている場合は申し訳ありません。検索しましたが、答えが見つかりませんでした(これは「簡単な」質問だと思います) )。

私は自分のウェブサイトに連絡先ページを追加したかったのですが、 このチュートリアル を見つけたので、それに従いました。フォームの検証まで、すべてが正常に機能しました。私はRequiredのみを使用し、form.validate()は常にfalseを返しました。コードに触れず、フォームクラスのすべてのRequiredを削除すると、正常に機能し、form.validate()はtrueを返します。

理由がよくわかりません。validate_on_submit()を使用する必要があることをよく読んでいますが、使用するとエラーが発生します。 *「ClassName」オブジェクトには属性がありません「validate_on_submit」*

コードの関連部分は次のとおりです。

Index.py

@app.route('/contact', methods=['GET','POST'])
def contact():
form = ContactForm()

if request.method == 'POST':
    if form.validate() == False:
        flash('All Fields are required.')
        return render_template('contact.html', form=form)
    else:
        return 'Form posted'
Elif request.method == 'GET':
    return render_template('contact.html', form=form)

forms.py

from wtforms import Form, TextField, TextAreaField, SubmitField, validators,ValidationError 

class ContactForm(Form):
  name = TextField("Name", [validators.Required()])
  email = TextField("Email")
  subject = TextField("Subject")
  message = TextAreaField("Message")
  submit = SubmitField("Send")

contact.html

<div id="contact">
    {% for message in get_flashed_messages() %}
        <div class="flash">{{ message }}</div>
    {% endfor %}
  <form action="{{ url_for('contact') }}" method=post>

    {{ form.name.label }}
    {{ form.name }}

    {{ form.email.label }}
    {{ form.email }}

    {{ form.subject.label }}
    {{ form.subject }}

    {{ form.message.label }}
    {{ form.message }}

    {{ form.submit }}
  </form>
 </div>

[名前]フィールドに何かを入力しても、「フォームが投稿されました」という文字列が表示されません。

前もって感謝します、

13
Mimu

リクエストの値を使用してフォームインスタンスを初期化する必要があります。

from flask import request

@app.route('/contact', methods=['GET','POST'])
def contact():
    form = ContactForm(request.form)
    if request.method == "POST" and form.validate():
        # do something with form
        # and probably return a redirect
    return render_template("contact.html", form=form)

これは、質問でリンクするチュートリアルよりも優れたチュートリアルです: http://flask.pocoo.org/docs/patterns/wtforms/

チュートリアルのテンプレートレンダリングコードを見て、フォームフィールドエラーをレンダリングしていることを確認してください。フォームが投稿されたが検証されない場合、コードはrender_templateにフォールスルーし、フォームインスタンスにフィールド検証エラーが含まれます(詳細については、チュートリアルとWTFormsのドキュメントを参照してください)。

11
codeape

MiguelGrinbergの著書「FlaskWebDevelopment」のデモコードに従ってログインフォームをテストしているときは、常にform.validate_on_submit()に失敗します。だから私はデバッグする方法を見つけるべきだと思います。

私が採用しているデバッグアプローチは、以下のコードをapp/auth /views.pyに追加することです。

flash(form.errors)

次に、ログインページにアクセスすると、原因が表示されます。

errors={'csrf_token': ['CSRF token missing']}

したがって、form.errorsメッセージを使用してデバッグすることをお勧めします。

23
wcb1

問題が発生したばかりで、解決策はテンプレートのフォームのすぐ下にhidden_tagを追加することでした。

...
<form action="{{ url_for('contact') }}" method=post>
{{ form.hidden_tag() }}
...
9
Pavel Vergeev

@Paul Vergeevとして、次を追加するだけです。

_<form action="{{ url_for('contact') }}" method=post>
{{ form.csrf_token }}
_

フォームにはバリデータが含まれているため、これが必要です。したがって、htmlフォームに「Hidden」タイプの「入力」が追加されます。 HTMLにこの非表示のトークンがないと、バリデーターはユーザーの入力を検証できず、検証の結果は常にFalseになります。

_{{ form.hidden_tag() }}
_

hTMLコードにすべての非表示の入力フィールドが含まれます。ただし、ページには表示されません。

_{{ form.csrf_token }}
_

hTMLコードに非表示のcsrf_token入力フィールドのみが含まれます。ただし、ページには表示されません。

もう1つ行うこと:アプリの_SECRET_KEY_を構成する必要があります。これを行うには、アプリの初期化のすぐ下、つまりapp = Flask(__name__)の直後に_app.config["SECRET_KEY"] = "a secret key you won't forget"_を含めます。

これはすべて、WTFormsバリデーターがサイトをCSRF(c-surfと発音されることが多い)から保護するための方法です。 CSRFの詳細も読むことができます ここ

2
John Mutuma