Sunday, April 15th, 2012

Stay tuned for a Django AJAX tutorial

Today I was on the django-users Google group and noticed an interesting post titled Working Hello World Ajax example via django pleeeease. Here is what the user was asking:

I've been attempting the most basic ajax call (.load()  )  through
django for over a month now - each time trying a different method or
tutorial none with success. Can someone post a working paradigm for
whatever django csrf, firefox, ect. workaround they use?

I can get jquery .load() to load content from an external file with
static files , no django. Same file served through django/templating
and the ajax is blocked. This is the general jquery call:

$(document).ready(function() {
    $('.list').click(function () {
$('#message').load('namesinfo.htm li');
        return false;
    });
});

To make things worse I found that Firefox/Chrome breaks Jquery's
sample 'Tabs: load content via ajax'  in the Themroller download. But
it works in IE :/. Same .load() calls occuring here. Just working w
static files no django. Could it be related to Firefox/Chrome?

I am pretty sure it is not: static file serving issues. I have heard
comments to follow django 'csrf / ajax' and included their sameOrgin
script to no avail. :

https://docs.djangoproject.com/en/dev/ref/contrib/csrf/

A similar issue even though this guys solution is hard to understand:

http://stackoverflow.com/questions/6643242/jquery-load-not-working-in-django

Interesting, this user never searched for any Django specific app which could perform the given task, but rather works with jQuery manually in hopes that it will work. I think most new comers to Django, who were perhaps in the world of PHP or another language would attempt to build their app. In Django, there two AJAX frameworks, named Dajaxice and Dajax. They take all the complex work of setting up CSRF headers and such away from the developer. My personal profile site, is build using this technology and it just works, as one would expect.

The replies from the many Django developers in the group never mention these two AJAX frameworks... Someone goes and points the user to a blog with this rather awful code:

import os
from django.http import HttpResponse
...
def ajax(req):
    if req.is_ajax():
        stdout = os.popen("/path/to/script.py")
        output = stdout.read()
        return HttpResponse(output)

Who does this? Who forks a python script to obtain the result for an AJAX query?!?! Wouldn't it be better to just port the code over to your application? I really don't understand some programmers and their awful coding habits. By the way, this code is incompatible with some cloud services, namely Google App Engine.

The user later finds out about Dajaxice, as he was unable to solve the issue, and nobody provided a working example, as he requested.

Because of this, I want to create an easy to follow tutorial on how to get up and running with Dajaxice and Dajax, as easily and as quickly as possible. Please look forward to this tutorial and the completion of my Django tutorial in the next few weeks in my tutorials section.

The first tutorial in the set is now available!

Comment #1: Posted 2 years, 5 months ago by Andrew Swihart

I think doing AJAX manually using $.ajax and with "if request.is_ajax()" in regular Django views is easier and more rewarding in the long run, rather than turning to something like Dajax.

Why do you want to be tied to this dependency? The worst thing about it is that it forces you to follow a poor convention of inserting inline javascript in your HTML. From the Dajax docs, for example you put this in an element you want to fire an event: onclick="Dajaxice.example.myexample(my_js_callback);". You're also forced to structure your views around Dajax. How does this help? In the end it doesn't seem to bring any significant benefits that I'm aware of.

All you need is jQuery: learn how to use $.ajax, it's really not hard to grasp the basics. On the Django side, the request.is_ajax() method is there to use in your view to send a different response back to the $.ajax function. This keeps your views DRY, you can share parts of code common to regular and AJAX requests, rather than making new functions entirely for Dajax to use.The AJAX CSRF script (https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax) works perfectly well also.

If you start to build a sufficiently complex app, you'd be better off learning to hook up Tastypie and Backbone.js rather than to think you need something like Dajax.

Comment #2: Posted 2 years, 5 months ago by Kevin Veroneau

Thank you for your comment Andrew.

Using Dajaxice shouldn't tie you to it as a dependency, new projects can continue using the Dajaxice JavaScript code, which basically JSONify a standard javascript dictionary, adds a X-Requested-With header, along with a nice X-CSRFToken header. The rest of the routine Dajaxice generates is all standard JavaScript stuff, with no dependency on jQuery. Take a look at what is generated here: http://c262965.r65.cf1.rackcdn.com/dajaxice.core.js

Dajaxice just takes the headache of creating a similar function our of the developers way, and the JS function will work with other backend frameworks, I can guarantee that. If you use Dajax, then it's another story...

Why rewrite the wheel a billion times in every web application, when a JavaScript function already exists which can be used?

As for DRY, if your requesting data via AJAX, it's more than likely for a reason. When I use Dajaxice, the code which generates the JSON is not used elsewhere. My tutorial will focus on the DRY principal, most definitely.

Comment #3: Posted 2 years, 5 months ago by Andrew Swihart

Sorry but I don't know what you are referring to by re-inventing the wheel. if anything I would accuse Dajaxice of doing that. There's no good reason to use it over the established patterns I mentioned in my first comment.

Again, putting onclick="Dajaxice.example.myexample(my_js_callback);" in your HTML is really a poor practice, and of course it ties you to Dajax as a dependency without some, admittedly minor, re-working. Would you want to do this, for example, in a re-usable Django app? I think not. Further, you have a very limited subset of event triggers, such as `onclick`.

With Dajax, making changes to which element(s) trigger the ajax function involves cutting and pasting that snippet to the other HTML element(s) scattered in your template(s); whereas using a single $.ajax function, you could instead just alter your jQuery selector, to select a different, or multiple elements, change the Django view to send the request to, and change the js callback, all in one place, one time, not multiple and scattered all over your templates. And the overall volume of code is equal if not more with Dajax. I just don't see the benefits, but like I said, it seems to be kind of reinventing the wheel.

Comment #4: Posted 2 years, 5 months ago by Andrew Swihart

TIL: I take back the part about having a limited set of event triggers, there are more than I thought: http://www.w3schools.com/jsref/dom_obj_event.asp

Comment #5: Posted 2 years, 5 months ago by Kevin Veroneau

Andrew, seeing by how you think that Dajaxice can only be bound to specific DOM objects displays your knowledge for JavaScript greatly. Your example function "Dajaxice.example.myexample(my_js_callback);" is merely a simple JavaScript function, and can be placed anywhere you have a $.ajax, they are one in the same. I use Dajaxice functions with jQueryUI and it works wonderfully without the limitations you have described in your comments. You can place Dajaxice inside any JavaScript function, and even as a onTimeout/onInterval callback, imagine that! Look at the Dajaxice tutorial I have, and the section in the bottom shows what Dajaxice generates for the browser. Which is none other than the creation of a simple cross-platform HttpRequest object and calls that, nothing Django-specific about that. My example goes into how one would port a Dajaxice routine over to a different framework, if one so chooses.

There are also many portable apps which depend on other portable apps out there for Django, South being one of the most used dependents. No apps that I have used make use of Dajaxice, as I don't use apps which make use of user facing webpages. I use apps which add functionality, like tagging, or object-level permissions. I build the user facing content from scratch myself and tailor the apps I use for my particular requirements. Django is not a Joomla or a Drupal, where most apps/plugins do provide user facing components. The only major component Django offers which is user facing is the admin interface, everything else is up to the developers imagination(unless you use a sub-framework like Pinax or Django-CMS).

On a off-note, if you took time to look over the Dajaxice tutorial, I also noted that I will be creating a second tutorial for developers who do prefer to use jQuery, and it will be in the form of using class-based views and a JSON Mixin, which would be the best way to use this type of technology, and is very DRY. Dajaxice was made before class-based views made their debut, so this may be a better solution now. I just don't like having really messy functions with is_ajax and that_ajax all over the place. I prefer to practice clean coding, even if that means to occasionally not use DRY. Readable code is better than spaghetti/DRY code any day.

Comment #6: Posted 2 years, 5 months ago by Andrew Swihart

I am looking forward to your post, Kevin. I suspect I have a few things to learn about Dajax. It hadn't occurred to me that you could use the Dajaxice JS functions without pasting them inline in the HTML, admittedly this is because I looked at Dajax a long time ago, and I've learned a lot since them, but now of course it seems obvious. But I'm still wondering what the perceived advantages are that you see, other than including the AJAX CSRF fix script, which is trivial (not sure why you said it's complex).

The nice thing about using the is_ajax() function is you can treat requests from JS-enabled clients different than those without JS turned on (so-called unobtrusive javascript). Admittedly, even I question how important this is these days, but it is a best practice nonetheless.

About Me

My Photo
Names Kevin, hugely into UNIX technologies, not just Linux. I've dabbled with the demons, played with the Sun, and now with the Penguins.




Kevin Veroneau Consulting Services
Do you require the services of a Django contractor? Do you need both a website and hosting services? Perhaps I can help.

This Month

If you like what you read, please consider donating to help with hosting costs, and to fund future books to review.

Python Powered | © 2012-2014 Kevin Veroneau