Flask-WTF - validate_on_submit()永远不会执行

时间:2012-05-23 15:18:28

标签: python forms validation flask wtforms

我正在使用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)

现在问题是,如果你查看我的print语句,它总是打印提交,但它永远不会打印有效,并且从不执​​行validate_on_submit()。为什么呢?

7 个答案:

答案 0 :(得分:41)

您没有在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 -

I created an example on GitHub.

答案 1 :(得分:12)

你可以打印错误

print form.errors

app.logger.debug(form.errors)

如果您遇到csrf错误,则应在模板中设置 form.csrf_token

答案 2 :(得分:2)

在模板html文件中的标记之后插入:

 {{ form.csrf_token }} 

答案 3 :(得分:1)

如果我在每次请求之前都没有登录,那么我正在清理烧瓶会话。这导致了这个问题。

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

答案 4 :(得分:1)

当我尝试在我的模板中对FormField进行迭代时,我遇到了这个问题。我必须为FieldList表单嵌入一个hidden_​​tag元素,为FieldList表单嵌入一个,搜索模板注释以查找关键字&#34; HIDDEN TAG&#34;

FieldForm

答案 5 :(得分:0)

我认为API已更改。也许尝试更改

from flask.ext.wtf import Form

收件人:

from flask_wtf import Form

答案 6 :(得分:0)

我花了几个小时来调试Flask-WTF的验证问题。像许多其他问题一样,该问题是CSRF验证问题。但是,我的原因并不是我发现的任何常见问题。

CSRF的标准Flask-WTF实现要求将两个内容交付给浏览器。

一个:隐藏的CSRF表单字段,例如

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

两个:会话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方法的所有操作失败。其中之一是Flaks-WTF设置会话cookie HTTP标头。

这可以通过在super()类中添加LocalFlask方法来解决,以便它继承Flask类的方法。

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