【问题标题】:Flask - wtforms: Validation always falseFlask - wtforms:验证总是错误的
【发布时间】:2014-01-21 05:07:47
【问题描述】:

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

我想在我的网站中添加一个联系页面,我找到了this tutorial,所以我关注了它。 在表单验证之前一切正常。我只使用 Required 并且 form.validate() 总是返回 false。如果我不碰我的代码,并且我删除了表单类中的每个必需项,它就可以正常工作,form.validate() 返回 true。

我真的不明白为什么,我读了很多应该使用 validate_on_submit(),但是如果我使用它会出现错误:*'ClassName' object has no attribute '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>

即使我在名称字段中写了一些东西,我也从未收到“已发布表单”字符串。

提前致谢,

【问题讨论】:

    标签: python validation flask wtforms


    【解决方案1】:

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

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

    【讨论】:

    • 这不再解决问题。请参阅下面与 CSRF 令牌相关的修复。
    【解决方案2】:

    当我按照 Miguel Grinberg 的“Flask Web Development”一书中的演示代码测试登录表单时,我总是失败 form.validate_on_submit()。所以我觉得我应该想办法调试一下。

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

    flash(form.errors)
    

    然后当我运行到登录页面时它显示了罪魁祸首:

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

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

    【讨论】:

    • 这是我的错误。我使用的是 form.hidden_​​field 而不是 form.hidden_​​tag()。
    • 你救了我的命
    • 我刚开始使用 Flask 进行开发,我不知道如何调试。谢谢你,这是一个示例用法:stackoverflow.com/a/13587339/343215
    • 用你的笔记我可以得到错误:The CSRF tokens do not match。我已经在网上搜索过,但它们对我没有用,您对这个问题有任何想法吗?我已经通过{{ form.hidden_tag() }}{{ form.csrf_token }}在表单中设置了csrf
    【解决方案3】:

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

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

    【讨论】:

    • @SARose 这有效,因为否则会发生这种情况:stackoverflow.com/a/34570528/3694363 - 由于缺少 CSRF 令牌,验证失败。所以要修复它,我们需要在表单中插入 CSRF 令牌作为隐藏输入值。所以{{ form.hidden_tag() }} 实际上在 HTML 中插入了类似这样的内容:&lt;input type="hidden" name="csrf-field-name" value="csrf-token-here"&gt;。 csrf-token 现在随表单一起发送,验证通过。
    【解决方案4】:

    作为@Paul Vergeev,只需添加:

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

    这是必需的,因为您的表单包含验证器,因此在您的 html 表单中添加了“隐藏”类型的“输入”。如果您的 html 中没有此隐藏标记,验证器将无法验证您的用户输入,并且验证结果将始终为 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

    【讨论】:

    • 谢谢@John Mutuma ...这节省了我的时间:)
    猜你喜欢
    • 2023-02-02
    • 2013-11-15
    • 2014-02-05
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 2016-05-30
    • 2014-02-08
    相关资源
    最近更新 更多