Flask - wtforms:验证始终为false

时间:2014-01-03 13:52:20

标签: python validation flask wtforms

首先,我是python和Flask的新手,所以如果我的问题很愚蠢,我很抱歉。我搜索它但从未找到答案(我猜这应该是一个“简单”的答案)。

我想在我的网站上添加一个联系页面,我找到this tutorial所以我跟着它。 一切正常,直到表单验证。我只使用必需 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>

即使我在“名称”字段中写了一些内容,我也从未收到“Form posted”字符串。

提前致谢,

4 个答案:

答案 0 :(得分:17)

当我在Miguel Grinberg的书“Flask Web Development”中按照演示代码测试登录表单时,我总是无法使用form.validate_on_submit()。所以我想我应该找到一种调试方法。

我正在采取的调试方法是将以下代码添加到app / auth / views.py:

flash(form.errors)

然后它向我展示了当我跑到登录页面时的罪魁祸首:

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

所以我建议使用form.errors消息进行调试。

答案 1 :(得分:8)

您必须使用请求中的值初始化表单实例:

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文档)。

答案 2 :(得分:5)

刚遇到问题,解决方案是在模板中的表单下添加hidden_tag

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

答案 3 :(得分:1)

作为@Paul Vergeev,只需添加:

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

这是必需的,因为您的表单包含验证器,因此添加了一个输入&#39;类型&#34;隐藏&#34;在你的HTML表单中。如果您的html中没有此隐藏的令牌,则验证程序无法验证您的用户&#39;输入和验证结果将始终为False。

{{ form.hidden_tag() }}

将包含html代码中的所有隐藏输入字段;但它们不会显示在页面上。

{{ form.csrf_token }}

将在html代码中仅包含隐藏的csrf_token输入字段;但它们不会显示在页面上。

还有一件事要做:您必须配置自己的应用SECRET_KEY。通过在应用初始化下方{即app.config["SECRET_KEY"] = "a secret key you won't forget"之后加app = Flask(__name__)来实现此目的。

所有这些都是WTForms验证工具保护您的网站免受CSRF攻击的一种方式(通常称为c-surf)。您还可以阅读有关CSRF here的更多信息。