Hijaxing Form Submission: Writing The View

After writing about how to use Mootools to hijax form submission I thought I should follow it up with how to integrate this with the backend code. In this case it’s Django, so all of the code is contained in a view which will simply return HTML in response to a regular POST and JSON to a XMLHttpRequest. Below is some sample code which demonstrates the idea:

def contact(request):
    """Sample view to demonstrate using newforms with both hijaxed and POSTed forms"""
    if request.method == 'POST':
        contact_form = ContactForm(request.POST)
        xhr = ('xhr' in request.GET)
        if contact_form.is_valid():
            Contact.objects.create(name=contact_form.cleaned_data["name"], \
                                    email=contact_form.cleaned_data["email"], \
                                    comment=contact_form.cleaned_data["message"], \
                                    is_xhr=xhr)
            if not xhr:
                return HttpResponseRedirect(urlresolvers.reverse('public_contact_success'))
            response_dict = {'message': 'Thanks, your message has been received!', 'cssClass': 'success'}
        else:
            response_dict = {'errors': contact_form.errors,
                                    'message': 'Check the above error messages and try again',
                                    'cssClass': 'fail'}
        if xhr:
            return JsonResponse(response_dict)
    else:
        contact_form = ContactForm()
    return render_to_response('front/contact.html',
                                {'form': contact_form},
                                context_instance=RequestContext(request))

If you’ve used Django before, the majority of the code will look familiar and there are only a couple of bits which we need to add to enable it to handle both a standard POST and an XMLHttpRequest.

Firstly, we need to check to see which one we’re dealing with. If you take a look at the previous article, you will see that we use Mootools to add an ‘xhr’ key to the form action which allows us to determine where the request origninated (XMLHttpRequest or standard POST) and return the appropriate content — HTML for the POST and JSON for the XMLHttpRequest request.

After checking we’re dealing with a POST request, we populate an instance of our ContactForm with the POSTed data and test for the existence of the ‘xhr’ key and set our xhr variable accordingly: True if the form was submitted via an XMLHttpRequest and False if it is a standard POST. We can then check the validity of the form and either save the contact or return any errors.

If the submission was a standard POST, the user is simply redirected to a success page or returned the same page complete with errors depending on whether validation succeeded. However, if the form was submitted via an XMLHttpRequest we create response_dict and set a number of key-value pairs:

  • message - simple message string to indicate success or failure
  • cssClass - used to style the message string depending on whether or not there were errors
  • errors - will exist if the form failed validation and will be populated from the contact_form.errors dictionary

This dictionary is then serialized and returned to the browser as JSON using the JsonResponse helper class (borrowed from Simon Willison’s ajax slides from the Django Masterclass presentation). The parsing of the JSON, creation of the HTML elements and rendering is described in the previous article, so go check it out if you’re not sure.

Easy, isn’t it!

2007-09-07