Yeah this always bugged me too.
There's the javascript-rendered-with-Django-template-language method similar to what you've displayed above, however, I found pretty quick that this can easily become too cumbersome when the javascript is stored in an external file.
There are probably many ways to attack this problem, but I created a simple helper app to allow url resolution via AJAX. There are two parts 2 parts to it -- the server side url/view which returns the value and the client side script that that provides access to it.
It seems easier than it actually is. You will frequently want to pass arguments into the resolve
function and often the order of these arguments is very important. To maintain the order, when I pass the arguments back to Django, I orient them on the querystring with the key being the # of their order.
Once included (the javascript depends on jQuery), you can access it with...
// Equivalent to {% url blog_view_post post_id %}
var url = Django.reverse('blog_view_post', [post_id] );
On the server side...
javascript/views.py
from django.http import HttpResponse
from django.core.urlresolvers import reverse
def reverse_url(request, url_name):
# Turn querystring into an array of couplets (2x list)
# arg_couplets = [ ('key', 'value'), ('key', 'value') ]
arg_couplets = request.REQUEST.items()
# Sort by keys
arg_couplets.sort(lambda x,y: cmp(x[0], y[0]))
# Collapse list into just the values
args = [c[1] for c in arg_couplets]
try:
if args:
return HttpResponse(reverse(url_name, args=args))
else:
return HttpResponse(reverse(url_name))
except:
return HttpResponse()
On the client side... (make sure to include this in your template)
/media/django-javascript.js
(function($) {
Django = function() {
return {
reverse: function(name, args) {
var ret;
var arguments = {};
var c = 0;
// Convert args to keyed dictionary
for (i in args) {
arguments[c] = args[i];
c++;
}
$.ajax({
async: false,
url: '/javascript/reverse/' + name + '/',
data: arguments,
success: function(html) {
ret = html;
}
});
if (ret.length > 0) {
return ret;
}
else {
return null;
}
}
}
}();
})(jQuery);
On a side note, I've also done this for MEDIA_URL
and some other often used settings.