Caffeinated Simpleton

Django round 2

Last year when I was going through the various python frameworks, I eventually dismissed Django in favor of TurboGears. From TurboGears I settled on Pylons as my web framework of choice, and excepting some quirks and some bad documentation, I’ve been very happy.

Last night I had the privledge of revisiting Django to do a programming problem as part of an interview. I was tasked with making a little blog system that supported pingbacks. Having a lot more experience with frameworks now, I was able to really sit back and think about what I liked and what I didn’t, with respect to Pylons.

First of all, the emphasis on loosely coupled components is terriffic. One of the major problems we realized with harmonize was that our componentization was not fine grained enough and required too much knowledge of the code base to effectively navigate. Django is right to emphasize this from the beginning.

Django’s documentation is also quite a bit better organized than Pylons. They have a standardized approach that details all their components, and good tutorials and an alright book. On the other hand, the documentation for pylons is spotty and disorganized, with the documentation for its components being hit and miss. The docs for SQLAlchemy are second to none, but the docs for Beaker, the caching framework shipped with Pylons, barely exist.

The actual components of Django could use some help, however.

Django does not have a robust web server built in, like Pylons, so the recommended deployment strategy is with mod_python and Apache. This is hardly the lightweight, scalable approach that has become popular lately. I feel that an excellent static web server that can also serve as a reverse proxy is a great way of getting the most out of your servers. When developing new apps, you don’t want to be giving huge amounts of memory to apache. Your young app is most likely going to need that memory!

Django’s model is pretty good, but it clearly lacks the power that SQLAlchemy has. SQLAlchemy is an amazing bit of technology with support for everything from programmatically constructing SQL to sharding databases to a fully declarative ORM. Django’s model is just an ORM. I didn’t find querying to be very intuitive either (attributes just magically appear in objects that represent relationships), but it may just be that I am used to SQLAlachemy’s model. SQLAlchemy uses a “session” in a way that makes a lot of sense once you read a bit about it. I never know when Django is flushing transactions because there’s no real concept of a session.

By far the worst part of Django is the templating system. Perhaps I wasn’t using it correctly, but I hated it. After spending all summer with a robust and powerful templating solution in Pylons (Mako), I was completely taken aback at the simplicity and incompleteness of the Django solution. Beyond optimizations like the lack of compiling and caching of templates, the Django system doesn’t even support basic python syntax. You can pass variables, define blocks, and do basic if statements and loops, but beyond that, you can’t actually actually execute any code. Simple things like accessing a single element of a list seemed to be unsupported. I could not import modules or call functions, and forget about blocks of python code.

The syntax itself of the templating system seemed poorly thought out. The template tags did not look like html tags, python code, or the code of any other language. Instead they use “{% %}” to denote blocks and “{{ }}” to denote where the values of variables should be inserted. This seems completely arbitrary. I feel that Mako’s habit of making its syntax look like regular tags is much cleaner and natural.

Finally there was the URL routing system, in which I had to define the route of every URL I wanted. This may have just been my own lack of knowlege, but I really like the Routes strategy (if not Routes itself) in Pylons. Routes just automatically routes urls to a class and function, but allows you to specify custom routes that behave very similarly to Django’s. The difference is that you don’t need to specify a complicated regular expression in the average case. Normally things just work.

Django defends their URL mapper by saying that other solutions are Black Magic and that explicit is better than implicit. I think that’s ridiculous. You can easily look in the routes.py file in a pylons project to see exactly how they achieve their “Magic”. Furthermore, Django uses magic all over their model, both in how objects are constructed and in how you query the model. The Django URL routing could definitely benefit from some useful defaults.

Well, I think that’s all I want to say on the topic right now. Django seems like a very nice framework, and a bit more organized than Pylons. In the end, however, I’ll stick with the superior components Pylons ships with, and maybe try to help them out with their organizational issues.

comments powered by Disqus