Overview

Tonight I wanted to put together a simple form in the sidebar of a Django page that submits via ajax and then reloads with a new version of the same form.  Hunch.com sort of does this (they don’t use a form), but they have a question that, when answered, comes back with a new question so that the site can continuously learn new tidbits about you:

hunch_side

At first it seemed I would need to first pass an object to my index view and load the form template by passing along the context.  This seemed roundabout though as the index didn’t need to see the object at all.  The solution I settled on was to create one form view that returns a json object containing information that would fill the form.  I would request this via ajax at page load and with subsequent form submissions.  The code remains reusable and no efforts are duplicated.

The View
The view is pretty simple. Handle the post request if it is a post then return a json object representing our form information.

def item_form(request):
     if request.method == "POST":
         form = ItemForm(request.POST)
         ... handle form validation ...
 
     itemset = Item.objects.all()
     data = serializers.serialize("json", itemset)
     return HttpResponse(data, mimetype="application/javascript")

The Template
First we’ll write the html and then fill in the javascript. Notice that I’ve left some of the elements empty as these will be filled in when we get passed back a json object. We’ll write a javascript function submit_item_form to handle posting the appropriate form fields via ajax. It is advisable to hide the sidebar-item element to begin with and then show it after loading content so that the form appears gracefully with the page load.

<div class="sidebar-item">
	<form action="/ajax/item_form" method="post" id="item_form">
		<h2></h2>
		<img src="" class="small-item-image" />
		<input type="text" name="name" value="" />
		<input type="submit" value="Submit" 
                      onclick="submit_item_form('item_form'); return false;"/>
	</form>
</div>

Next the jquery that loads the json object. Jquery’s getJSON method automatically parses the response string into a json object.

$(function() {
	$.getJSON("/ajax/item_form", function(data) {
		fill_item_form(data);
	});
});

And then the method that loads the data returned into our prefilled form:

function fill_item_form(json)
{
	var item = json[0]; // we'll only use 1 item for this example
 
	$(".sidebar-item h2").html(item.fields.title);
	$(".sidebar-item .small-item-image").attr("src", item.fields.photo_url);
 
	$(".sidebar-item").show();
}

Now we need to handle the form submission and we’re golden:

function submit_item_form(form_id)
{
	$.ajax({
		type: "POST",
		url: "/ajax/item_form",
		data: $('#' + form_id).serialize(),
		dataType: "json",
		success: function(json){
		     fill_item_form(json);
	        }
	});
}

Now the same function that loads our content reloads the content we get back after submitting the form so that a new form can be submitted.