from django import forms
from django.conf import settings
from django.template.defaultfilters import striptags


class AjaxBaseForm(forms.BaseForm):
    def errors_as_json(self, strip_tags=False):
        error_summary = {}
        errors = {}
        for error in self.errors.iteritems():
            errors.update({error[0] : unicode(striptags(error[1]) \
                if strip_tags else error[1])})
        error_summary.update({'errors' : errors })
        return error_summary


class AjaxModelForm(AjaxBaseForm, forms.ModelForm):
    """Ajax Form class for ModelForms"""


class AjaxForm(AjaxBaseForm, forms.Form):
    """Ajax Form class for Forms"""


Example Usage:

    #forms.py
    from my_app import AjaxForm

    class MyForm(AjaxForm):
        first_name = models.CharField(max_length=40)

    #views.py
    try:
        import json
    except ImportError:
        import simplejson

    from django.views.shortcuts import render_to_response

    from my_app.forms import MyForm

    def my_view(request):
        if request.method == 'GET':
            form = MyForm()
        else:
            form = MyForm(request.POST)
            if form.is_valid():
                response = {'success' : True}
            else:
                response = form.errors_as_json()
            return HttpResponse(json.dumps(response, ensure_ascii=False),
                mimetype='application/json')
        return render_to_response('my_template.html', {'form' : form})

Sample JavaScript implementation to handle json returned
using jQuery and the jQuery Form plugin. You'll need to add a hidden field
to your form to hold the value for the form prefix, if you're using one.

This example leverages the jQuery Form plugin:
http://www.malsup.com/jquery/form/

    jQuery(function($){
        var login_form = $('#login');
        login_form.ajaxForm({
            url : this.action,
            dataType : 'json',
            success : function(json)
            {
                if (json.errors != undefined)
                    process_form_errors(json, login_form)
                else
                    //do something if there aren't errors
            }
        }); 
    });

    function hide_form_errors()
    {
        $('.errorlist').remove();
    }

    function process_form_errors(json, form)
    {
        hide_form_errors();
        form.clearForm();
        errors = json.errors;
    
        if (errors.__all__ != undefined)
            form.append(errors.__all__);

        prefix = form.find(":hidden[name='prefix']").val();

        prefix == undefined ? prefix = '' : prefix = prefix + '-';
        for (field in errors)
            $('#id_' + prefix + field).after(errors[field]);
    }