Flask-WTF - validate_on_submit() 永远不会执行
Posted
技术标签:
【中文标题】Flask-WTF - validate_on_submit() 永远不会执行【英文标题】:Flask-WTF - validate_on_submit() is never executed 【发布时间】:2012-05-30 04:19:05 【问题描述】:我正在使用 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() 永远不会执行。为什么?
【问题讨论】:
WTF 验证链接。如果开始日期大于结束日期,则比较两个日期然后给出错误。 ***.com/a/53804438/9477847 【参考方案1】:您没有在 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.
【讨论】:
非常感谢!这是确切的问题!我的表单中没有包含 csrf 字段。尝试用 form.csrf
解决它没有用,但是这样做: form.hidden_tag()
解决了这个问题!您对错误打印的看法也是正确的,很高兴知道它现在是如何正常工作的!
很高兴为您提供帮助。如果您正在运行 WTForms 0.6 或更高版本,form.csrf
将变为 form.csrf_token
,因此请注意这一点,但 form.hidden_tag()
也可以正常工作。
这让我做噩梦了。非常感谢。
想知道为什么文档中缺少这个关键部分。谢谢!【参考方案2】:
你可以打印错误
print form.errors
或
app.logger.debug(form.errors)
如果您遇到 csrf-error,您应该在模板中设置 form.csrf_token。
【讨论】:
感谢您的提示,但 'print form.errors' 会打印 。仍然 form.validate() 返回 False 我想知道如何调试 Flask 表单验证问题。很好【参考方案3】:我在尝试渲染 FormField
在我的模板中对我的 FieldList
进行迭代时遇到了这个问题。我必须嵌入两个 hidden_tag 元素,一个用于FieldList
表单,一个用于FieldForm
表单,在模板 cmets 中搜索关键字“HIDDEN TAG”
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>
【讨论】:
【参考方案4】:在模板 html 文件的标签之后插入:
form.csrf_token
【讨论】:
【参考方案5】:如果我在每次请求之前都没有登录,我正在清除烧瓶会话。这是导致此问题的原因。
@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'))
【讨论】:
【参考方案6】:我认为 API 已更改。也许尝试更改
from flask.ext.wtf import Form
到:
from flask_wtf import Form
【讨论】:
【参考方案7】:我花了几个小时调试 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__)
【讨论】:
以上是关于Flask-WTF - validate_on_submit() 永远不会执行的主要内容,如果未能解决你的问题,请参考以下文章