I was wondering how requests via AJAX can be implemented into Django framework. So I wrote a small application and hooked it into an existing Django project for testing purposes. The application has two models, Employee and Project, and two methods. The first method fetches data from the project and employee tables and renders that data onto a template. The second method takes care of the AJAX request and returns a JSON string. There is javaScript code embedded on the template itself, which is responsible for the AJAX requests and manipulating DOM on a successful response.
My project structure looks like this:

The models:
from django.db import models
class Employee(models.Model):
name = models.CharField(max_length=200)
def __unicode__(self):
return "%s" %(self.name)
class Project(models.Model):
name = models.CharField(max_length=200)
employee = models.ForeignKey(Employee)
def __unicode__(self):
return "%s, %s" % (self.name, self.employee)
The methods:
from django.http import HttpRequest, HttpResponse,HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import loader,Context
from django.utils import simplejson
from ajax.models import Employee, Project
class ProjectInfo(object):
"""
Container for project infos for easy iteration on
the template.
"""
def __init__(self):
self.project = None
self.in_charge = ""
self.employee_list = []
def simpleAjaxTest(request):
"""Renders some data onto a template"""
project_list = []
employee_list = []
project_info_list = []
template = loader.get_template("ajax.html")
#Fetch data from database
projects = Project.objects.all()
employees = Employee.objects.all()
for employee in employees:
employee_list.append(employee)
#For each project in the list create a new ProjectInfo object
for project in projects:
pro = ProjectInfo()
pro.project = project
pro.in_charge = project.employee
pro.employee_list = employee_list
project_info_list.append(pro)
context = Context({'project_info_list' : project_info_list,})
return HttpResponse(template.render(context))
def ajaxResponse(request):
"""Reads some data from request and responses a Json string"""
project_id = request.GET["project_id"]
employee = request.GET["employee"]
response_dict = {"project_id": project_id,"employee": employee}
return HttpResponse(simplejson.dumps(response_dict), mimetype='application/javascript')
As already stated above, the first method fetches some data from tables and renders it onto the template. The result looks like this:

The second method, the ajaxResponse method, is called on the onchange event of the drop down boxes. From the request it reads the project_id and employee parameters and returns them in a JSON string, which then is handled by the handleSuccess function of the callback. But more to that later.
The javaScript code:
<script type="text/javascript">
function doRequest(x){
var sUrl;
var drop_down_box = document.getElementById(x).value;
// The value of drop_down_box contains the project_id
// and employee name separated by a comma. Need to split it to built
// the sURL later.
var jsonString;
var data = drop_down_box.split(",")
var output = document.getElementById("output")
var switch_column = document.getElementById("switch_" + data[0])
// Successful server Response.
var handleSuccess = function(o){
if(o.responseText !== undefined){
output.innerHTML = "<li>Transaction id: " + o.tId + "</li>";
output.innerHTML += "<li>HTTP status: " + o.status + "</li>";
output.innerHTML += "<li>Status code message: " + o.statusText + "</li>";
output.innerHTML += "<li>HTTP headers:<br/>";
output.innerHTML += o.getAllResponseHeaders + "</li>"
output.innerHTML += "<li>Server response: " + o.responseText + "</li>";
// Parse jsonString
jsonString = o.responseText
try {
var responseData = YAHOO.lang.JSON.parse(jsonString);
}
catch (e) {
alert("Invalid data returned");
}
// Change the employee in the "In Charge column with the one
// selected from the drop down box.
switch_column.innerHTML = responseData.employee
}
}
// Response failed.
var handleFailure = function(o){
if(o.responseText !== undefined){
output.innerHTML = "<li>Transaction id: " + o.tId + "</li>";
output.innerHTML += "<li>HTTP status: " + o.status + "</li>";
output.innerHTML += "<li>Status code message: " + o.statusText + "</li>";
}
}
// Callback
var callback =
{
success:handleSuccess,
failure: handleFailure,
argument: { foo:"foo", bar:"bar" }
};
// Ajax request
sUrl = 'http://localhost:8000/blog/ajax/submit/?project_id=' + data[0] +'&employee=' + data[1]
var transaction = YAHOO.util.Connect.asyncRequest('GET', sUrl, callback, null);
};
The complete template code can be viewed here, which also includes the javaScript code.
Basicly when you change the user in the switch column the onchange event of the drop down box calls the doRequest() function and passes the id (which actually consist of of the prefix “drop_” and the project_id) of the drop down box as argument. Then we read it`s value. Since the value actually contains two information, the project_id and employee name, I had to split that string separating it by comma.
var output = document.getElementById(”output”)
var drop_down_box = document.getElementById(x).value;
var data = drop_down_box.split(”,”)
var in_charge_column = document.getElementById(”in_charge_column_” + data[0])
The variable data[0] contains the project_id. The variable output is an HTML element which displays information on successful or failed response. Since we will update the employee in the “in_charge_column” on successful response from server with the name we have selected from the drop down box, we need to fetch it.
The AJAX request part:
// Ajax request
sUrl = ‘http://localhost:8000/blog/ajax/submit/?project_id=’ + data[0] +’&employee=’ + data[1]
var transaction = YAHOO.util.Connect.asyncRequest(’GET’, sUrl, callback, null);
sUrl contains the url string to the corresponding method on the server, the ajaxResponse() method. The mapping of this url to the method is defined in the url.py file.
The url.py:
from django.conf.urls.defaults import *
urlpatterns = patterns('ajax',
# Example:
(r'^$', 'views.simpleAjaxTest'),
(r'^submit/$', 'views.ajaxResponse'),
)
On a successful response from the server the handleSuccess function from callback will be executed. This method displays some information about the response and manipulated the “in_ charge_column”. It will update the column with the employee name which we have selected from the drop down menu.
handleSuccess:
// Successful server Response.
var handleSuccess = function(o){
if(o.responseText !== undefined){
output.innerHTML = "<li>Transaction id: " + o.tId + "</li>";
output.innerHTML += "<li>HTTP status: " + o.status + "</li>";
output.innerHTML += "<li>Status code message: " + o.statusText + "</li>";
output.innerHTML += "<li>HTTP headers:<br/>";
output.innerHTML += o.getAllResponseHeaders + "</li>"
output.innerHTML += "<li>Server response: " + o.responseText + "</li>";
// Parse jsonString
jsonString = o.responseText
try {
var responseData = YAHOO.lang.JSON.parse(jsonString);
}
catch (e) {
alert("Invalid data returned");
}
// Change the employee in the "In Charge column with the one
// selected from the drop down box.
in_charge_column.innerHTML = responseData.employee
}
}
Since I don`t have access to an online Django system where this could be hosted I will post some screenshots:
1.Select a employee from the drop down box.

2. See how it updates the “In Charge” column with the selected name.

So, using the YUI javaScript framework combined with the Django webframework makes it pretty simple to send AJAX requests.
If you have any questions related to this post, don`t be shy and post it in the comments section. I will try and answer your question asap.




Pingback: In the Wild for February 19, 2009 » Yahoo! User Interface Blog
#1 by Rigel on July 18th, 2009
Quote
Thank you for your tutorial.I am noive in python and Django both. I tried to run your code. I am facing an error
Exception Type: TypeError
Exception Value: ’str’ object is not callable
Exception Location: C:\Python26\lib\site-packages\django\core\handlers\base.py in get_response, line 86
#2 by Norman on July 18th, 2009
Quote
Hello Rigel,
can you provide a stack trace of the error message perhaps?
Here is how you can implement that into your code:
http://docs.python.org/library/traceback.html
Its way easier to figure out what is wrong using a stack trace.
My guess would be that you have forgotten a “%” sign in the __unicode__ methods of either the Employee or Project classes:
def __unicode__(self):
return “%s” %(self.name)
Notice the % sign between “%s” and (self.name).
greetings
Norman
#3 by Michael on February 8th, 2011
Quote
When creating innerHTML, or concatenating any large amount of strings for that matter, use the following method:
html = [];
html = “Transaction id: ” + o.tId + “”;
html = “HTTP status: ” + o.status + “”;
html = “Status code message: ” + o.statusText + “”;
…
output.innerHTML = html.join(”");
instead of:
output.innerHTML += …
output.innerHTML += …
Since it creates a whole new string and copies all the old contents to it on each += operation.
It also re-renders the HTML each time innerHTML is altered!
This is expensive and slow, and considered bad convention.
Someone correct me if I’m wrong or inaccurate.
#4 by admin on February 8th, 2011
Quote
You are right Michael, thanks for the feedback.