Django in JavaScript

by Marty Alchin on November 4, 2007 about Django

Well, this post isn’t very substantial, because I don’t really have much code to back up my plans in this area, but it’s time for me to post again on what I’ve worked out for using Django with Google Gears. It’s turning out to be a bit trickier than I thought, bu I think it’s still something worth working toward.

A large part of Django will have to be rewritten in JavaScript, but I think the real trick with this is finding a balance between what we can automatically discover and what needs to be provided explicitly. As far as I can tell, here are the things that will need to be ported to JavaScript.

The Model API doesn’t really need to be rewritten, since you won’t really need to be declaring models directly in JavaScript. Instead, models can be generated automatically based on their Python declarations, so the JavaScript side can use any approach necessary to make the database API available. That’s one side of the trade-off, where Python can automatically generate the necessary JavaScript to make the magic happen.

On the other side of the trade-off, however is the problem of views. I can’t imagine any reasonable way to automatically convert Python functions to JavaScript equivalents, so those will have to be rewritten on a per-view basis by the application author. This is definitely unfortunate, but it seems unavoidable. Obviously, less rewriting is best, so hopefully this can be the only place where it’s necessary.

Resting solidly between models and views, URL dispatching can be automatically generated according to existing Python code. The interesting trick here is that Python’s re module allows (and Django encourages) the use of named groups, which JavaScript’s regular expressions don’t. Since named groups allow regex groups to be in a different order than the functions to a view, it’s not reasonable to just remove the names and hope they work properly. Instead, it’s possible to create a wrapper around JavaScript’s existing regular expressions that will allow them to run with unnamed groups, only to have them converted to a named dictionary for use when dispatching views. I’ve actually made some headway on that front, and it looks promising.

Another problem with URL dispatching with named views is that views will have to be able to be dispatched using named arguments, which is another thing JavaScript doesn’t support. However, given some clever regex matching of a function’s declaration, it’s possible to introspect JavaScript functions and figure out what names were given to its arguments. This allows the separation that’s currently available in Python, so JavaScript views can be written using the same argument names that are provided to the Python views.

Another necessity of this method is the ability to invoke functions using named arguments. There’s no perfect way to do this in JavaScript, but it’s possible to set up a function to accept two arguments: a list and an object. These work similarly to *args and **kwargs in Python, allowing functions to be called without particular arguments, or with the arguments switched around. It looks something like this: my_view([request], {id: 5}). It’s pretty close to the way Python would handle this (my_view(request, id=5)), and it’s entirely possible. I have some basic code for that, but it’s not quite complete yet.

Using this named argument technique, it also becomes possible to implement a database API that uses specialty arguments similar to Django’s standard lookups. For example, Person.objects.filter({age__gt: 65}) would be a perfectly valid way to access a list of objects. More work on the database API would probably have to wait until the queryset-refactor branch makes its way into trunk, so that it’s more closely related to the Python capabilities. But at least the syntax is possible, and matches fairly closely to what’s currently used.

The template language is another difficult point. I think it would be possible to inspect views and figure out which templates they use, but it’ll be difficult to implement the template language in its entirety in JavaScript. Unfortunately, doing so will be essential to support dynamic pages, which is an important part of why we use Django in the first place. This will take some work, but I think it’s possible.

Forms shouldn’t be too terribly difficult to implement, I don’t think. It would probably be possible to inspect each field type to get its HTML output, but to get proper validation, I expect we’d have to rewrite each Field in JavaScript. This would already have to be done for model fields anyway, though, so I think it’s reasonable to have that requirement.

So, all in all, there’s a lot of Django that will have to be rewritten for the project as a whole, but fairly little that will have to be rewritten by each developer looking to use it. I think it’s reasonable to rewrite the generic views as part of django-offline, though, so that only custom app views will have to be handled separately. Exactly how this will be done is something I haven’t yet decided, but it’s obviously on the list.