20Aug

Django: Generating static javascript and CSS with reversed URLs via Templates

Posted by Elf Sternberg as django, programming, web development

One of the nifty things that Django provides is the
{% url backreference %} syntax, which allows
you to name the targets in your list of URL objects and then refer to
them by an explicit name. You can sometimes use the function name
instead, and Django has a way of turning the function name back into
the URL. It works fine as long as the signature of the backreference
and the signature of the function match.

It’s very nice for RESTful interfaces. But what about AJAXy webpages?
AJAX is all about D(X)HTML and the rendering and animation of user
interfaces in a broser, and there’s a lot of Javascript that comes
along with all that HTML and CSS. And embedded AJAX often comes with
its own set of URL calls. I mean, seriously, what if you want to write
something like this:

<example.js>=
$.getJSON(
"{% url results %}", {},
   function(resp) {
   $("#resultswrapper").html(resp.results);
});

Here, I want to replace the string “url results” with the url
that returns the results and shoves their visuals into the
“resultswrapper” HTML object, whatever it is.

You could do this in Django, making this a templatized object
and spewing it out every time. But often enough this URL
never changes during the lifetime of the program. This is
effectively javascript with a macro embedded in it that you want
substituted once, preferably at start-up. Well, I haven’t done the
start-up for you. But here’s a nifty little chunk of code that’ll do
URL reverse lookups in any static files in
your STATIC_DOC_ROOT directory (by the way, that
STATIC_DOC_ROOT setting is pretty useful for development, if you’re
serving static media out of your Django server, as devs frequently
do):

<addition to settings.py>=
import os
DIRNAME = os.path.normpath(os.path.dirname(__file__))
STATIC_DOC_ROOT = os.path.normpath(os.path.join(DIRNAME, 'static')) + '/'

And here’s the routine. Note that I’ve made it a Django command:
put it wherever you want and use it wisely:

<rendertemplates.py>=
from django.core.management.base import NoArgsCommand
from django.core.management.base import CommandError

from settings import STATIC_DOC_ROOT
from django.template import Template
from django.core.urlresolvers import reverse

import os
import os.path
import re

re_walker = re.compile(r'\.tmpl$')

class Command(NoArgsCommand):
    help = ("Run a series of templates through the Template handler to produce "
            "(semi) static files.  This is mostly useful for javascript "
            "handlers with Ajax calls in them that only need the urls "
            "defined when the application is first built or starts running.  It "
            "allows developers to use the {% url somethingorother %} syntax inside "
            "Ajax handlers without burdening the application at runtime.")

    def handle_noargs(self, **options):
        paths = [os.path.join(STATIC_DOC_ROOT, path[0], filename)
                 for path in os.walk(STATIC_DOC_ROOT)
                 for filename in path[2]
                 if re_walker.search(filename)]

        for fn in paths:
            fn_out = re_walker.sub('', fn)
            open(fn_out, 'w+').write(Template(open(fn, 'r').read()).render({}))

It’s not perfect (hey, I wrote it in about 20 minutes, mostly to
fix this problem in a quick and dirty fashion. Given that I didn’t
know how the innards of the Template class worked, and have never used
the new os.walk() function, this was pretty good.

As always, I’ve provided the source code for this.

4 Responses to Django: Generating static javascript and CSS with reversed URLs via Templates

doug

August 21st, 2009 at 6:48 am

You could also serve the script up with:

(r’dynmedia/js/file.js’, cache_page(direct_to_template, 60*60*24), {‘template’: ‘js/ajaxy.js’, ‘mimetype’: ‘text/javascript’})

Tha would serve a cached javascript file for 24 hours.

Elf Sternberg

August 21st, 2009 at 7:37 am

Yes, but you’re still serving it out of your Django server. In deployement, you’ll want to serve it out of your media and static server, the one that hits the filesystem rather than the database. You eventually want to convert it, and you’ll want to do so while still being able to use Django’s url references.

Jj’s blog » Generating Javascript Widgets with reversed URL endpoints in Django

August 22nd, 2009 at 10:39 pm

[...] I just read Elf stenberg’s solution on how to seve static Javascript with reversed URLs in Django. [...]

Jj

August 22nd, 2009 at 10:53 pm

I was going to put my solution here as a comment, but I put it on my blog.

Here’s how I do it:

http://jj.isgeek.net/2009/08/23/generating-javascript-widgets-with-reversed-url-endpoints-in-django/

Comment Form

Recent Comments