我正在尝试使用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
都会返回False
。即使我通过request.vars.mytext
访问用户的输入,我也需要自己验证它而不是使用web2py的功能。
我错过了什么?
答案 0 :(得分:3)
当您将session
对象传递给form.accepts()
时,它会通过向表单添加隐藏的_formkey
字段来自动实施跨站点请求伪造保护。提交表单时,会将此隐藏字段的值与会话中存储的值进行比较,如果匹配失败,则不接受表单。
您的代码存在两个问题。首先,只有在有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
对象中包含的隐藏字段。