简体   繁体   中英

How to validate a web2py form submitted via AJAX?

I'm trying to submit a form using web2py's ajax function as explained in the book , but using FORM instead of SQLFORM since I don't want the data to be stored in a database.

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>

Controller inside 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)

When the form is submitted ( request.ajax == True ), both form.accepts and form.errors return False . Even though I access user's input via request.vars.mytext , then I would need to validate it on my own instead of using web2py's capabilities.

What am I missing?

When you pass the session object to form.accepts() , it will automatically implement cross-site request forgery protection by adding a hidden _formkey field to the form. When the form is submitted, the value of this hidden field is compared with the value stored in the session, and the form is not accepted if the match fails.

There are two problems with your code. First, you only call form.accepts when there is an Ajax request, so the _formkey does not get generated and included in the original form. To correct that, try the following:

form.process()
if request.ajax:
    if form.accepted:

form.process() is just a shortcut for form.accepts(request, session) . Above, it is called even for the initial non-Ajax call when the form is created. This will generate the _formkey value and store it in the session.

Second, your Javascript code does not submit the whole form but only the mytext field, so the hidden _formkey value will not be posted back to the server. As a result, the form is not accepted (web2py does not display an error in this case, as such a failure would typically be the result of foul play).

I'm not sure it is documented, but the second argument to the ajax() function can instead be a jQuery selector, which will result in all form elements inside the selected element being serialized and submitted. So, try:

    ajax('{{=URL('ajax_test')}}', '#myform', 'output');

The #myform selector will result in the entire form being serialized, including the hidden fields included in the form object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM