如何验证通过 AJAX 提交的 web2py 表单?
How to validate a web2py form submitted via AJAX?
我正在尝试使用 web2py 的 ajax
函数作为 explained in the book 提交表单,但使用 FORM
而不是 SQLFORM
因为我不想要数据存储在数据库中。
ajax_test.html
{{extend "layout.html"}}
<h2>Form</h2>
{{=form}}
<script>
jQuery("#myform").submit(function() {
ajax("{{=URL('ajax_test')}}",
["mytext"], "output");
return false;
});
</script>
<h2>Output</h2>
<div id="output"></div>
里面的控制器default.py:
def ajax_test():
form = FORM(
INPUT(_type="text", _name="mytext", _id="mytext",
requires=IS_NOT_EMPTY()),
INPUT(_type="submit"),
_id="myform"
)
if request.ajax:
if form.accepts(request.vars, session):
return DIV("Form submitted.")
elif form.errors:
return TABLE(*[TR(k, v) for k, v in form.errors.items()])
else:
return DIV("Couldn't check form.")
return dict(form=form)
提交表单时 (request.ajax == True
),form.accepts
和 form.errors
return False
。即使我通过 request.vars.mytext
访问用户的输入,我也需要自己验证它而不是使用 web2py 的功能。
我错过了什么?
当你将session
对象传递给form.accepts()
时,它会通过在表单中添加一个隐藏的_formkey
字段来自动实现跨站请求伪造保护。提交表单时,将这个隐藏字段的值与session中存储的值进行比较,匹配失败则不接受表单。
您的代码有两个问题。首先,只有在有 Ajax 请求时才调用 form.accepts
,因此 _formkey
不会生成并包含在原始表单中。要更正该问题,请尝试以下操作:
form.process()
if request.ajax:
if form.accepted:
form.process()
只是 form.accepts(request, session)
的快捷方式。在上面,它甚至在创建表单时的初始非 Ajax 调用中也会被调用。这将生成 _formkey
值并将其存储在会话中。
其次,您的 Javascript 代码不会提交整个表单,而只会提交 mytext
字段,因此隐藏的 _formkey
值将不会回传到服务器。结果,表单不被接受(在这种情况下,web2py 不显示错误,因为这种失败通常是犯规的结果)。
我不确定它是否记录在案,但 ajax()
函数的第二个参数可以改为 jQuery 选择器,这将导致所选元素内的所有表单元素被序列化并提交。所以,试试:
ajax('{{=URL('ajax_test')}}', '#myform', 'output');
#myform
选择器将导致整个表单被序列化,包括 form
对象中包含的隐藏字段。
我正在尝试使用 web2py 的 ajax
函数作为 explained in the book 提交表单,但使用 FORM
而不是 SQLFORM
因为我不想要数据存储在数据库中。
ajax_test.html
{{extend "layout.html"}}
<h2>Form</h2>
{{=form}}
<script>
jQuery("#myform").submit(function() {
ajax("{{=URL('ajax_test')}}",
["mytext"], "output");
return false;
});
</script>
<h2>Output</h2>
<div id="output"></div>
里面的控制器default.py:
def ajax_test():
form = FORM(
INPUT(_type="text", _name="mytext", _id="mytext",
requires=IS_NOT_EMPTY()),
INPUT(_type="submit"),
_id="myform"
)
if request.ajax:
if form.accepts(request.vars, session):
return DIV("Form submitted.")
elif form.errors:
return TABLE(*[TR(k, v) for k, v in form.errors.items()])
else:
return DIV("Couldn't check form.")
return dict(form=form)
提交表单时 (request.ajax == True
),form.accepts
和 form.errors
return False
。即使我通过 request.vars.mytext
访问用户的输入,我也需要自己验证它而不是使用 web2py 的功能。
我错过了什么?
当你将session
对象传递给form.accepts()
时,它会通过在表单中添加一个隐藏的_formkey
字段来自动实现跨站请求伪造保护。提交表单时,将这个隐藏字段的值与session中存储的值进行比较,匹配失败则不接受表单。
您的代码有两个问题。首先,只有在有 Ajax 请求时才调用 form.accepts
,因此 _formkey
不会生成并包含在原始表单中。要更正该问题,请尝试以下操作:
form.process()
if request.ajax:
if form.accepted:
form.process()
只是 form.accepts(request, session)
的快捷方式。在上面,它甚至在创建表单时的初始非 Ajax 调用中也会被调用。这将生成 _formkey
值并将其存储在会话中。
其次,您的 Javascript 代码不会提交整个表单,而只会提交 mytext
字段,因此隐藏的 _formkey
值将不会回传到服务器。结果,表单不被接受(在这种情况下,web2py 不显示错误,因为这种失败通常是犯规的结果)。
我不确定它是否记录在案,但 ajax()
函数的第二个参数可以改为 jQuery 选择器,这将导致所选元素内的所有表单元素被序列化并提交。所以,试试:
ajax('{{=URL('ajax_test')}}', '#myform', 'output');
#myform
选择器将导致整个表单被序列化,包括 form
对象中包含的隐藏字段。