I spent my time in Hungary and Romania, and later in Belgium. It was no surprise when, years later, a friend gave me a box set of Django Reinhardt’s early recordings. It’s 2012 and I’m looking forward to Tarantino’s latest/next, Django Unchained. That I ended up using Django may then come as no surprise.
It was not, however, always the only option.
I. To Recap
It was 2007 and I was (re-)designing a database for an academic journal. We had to keep track of [1] books (to review or not) and book reviews, [2] manuscripts (submitted and out for review), and [3] some way or another the people who reviewed or worked or us. When I got the job my predecessor, a good friend, had already taken the journal into the digital age from their years using manilla folders and some other records. Perhaps a word processing document or two. My friend had produced a FileMaker Pro database that kept track of these three main pieces of data, but in a rather not-even-denormalized way (as it had never been normalized).
For example, the “Book” table had multiple author fields; queries on authors would therefore have to include all four fields, even if two through four were usually empty. We did not have separate editor or translator fields; they were treated the same as authors, but we could add an “Ed.” or “edited by,” etc. This, too, would lead to needlessly complicated queries. We did keep a table of “People” around, primarily for book reviewers, but note that there would be considerable overlap between book reviewers (their own People table), book authors (in the Book table), article/manuscript submitters and manuscript blind reviewers (both in the Manuscript table, separate fields). We kept track of our assistant/regional editors and other personnel in a Mac OS X “Addressbook” …
My job, partially, in addition to my editorial assistant duties, was to come up with a better system. We also talked with a commercial vendor that the press liked. It provided a CMS/DMS solution of sorts for manuscript submission. In particular, it outlined a rather rigid but mostly suitable workflow, and it had been tested with other journals. I went through the training (phone and online) for this product and liked it, and the press was willing to pay for it, more or less, but it had one problem: what we really needed to work on was our book review workflow, not manuscript submission. And this product was not flexible enough; in fact, the vendor had never even considered book reviews as something [1] a journal would want to manage that [2] would need their own workflow.
As previously outlined, [1] we (I?) concluded that we needed a web-frontend application with a relational database backend, [2] during my bibliographic research I learned about FRBR, and [3] I more or less decided to write the whole thing in Python (with which, to that point, I’d not really worked … oops!). The final question was, assuming I did not write everything from scratch—originally a consideration—what framework should I use?
II. The Options
Of Perl, PHP, Python, and Ruby I had entirely ruled out PHP, which was either fitting or ironic, as it was the only of the four with which I had any real experience. I had tentatively chosen Python, but I was still open, in theory, to Perl or Ruby.
Since I knew Scoop, and had already set up several Scoop sites, I considered it first … could I modify it easily enough for our ‘data types’? Sorta kinda not really was my conclusion. It had lots of features we did not need, and was not designed out of the box for what we wanted to do. That development would cease around the time that I was looking at it was unexpected. Mason was the other Perl option considered. It was less framework and more a way of using Perl like one would use PHP for web development.
Ruby on Rails was already a few years old by this point and so therefore a mature and popular option. Active Record was my introduction to ORMs. Before this I’d done a lot of pseudocode for this and other projects, and they’d come down to me dealing with handlers and declaring database cursors. This perhaps suggests a digression.
Sometimes you start with the “application” … the idea for a presentation, some information, an action and from there you pick a language, etc., and finally you get to a database, primarily as something to store data and state. Ours was a more boring and less innovative task: we just wanted to take a database, more or less properly normalized, and expose it on the web behind some user authentication. We began with the databae, needed a language on top of that to [a] access and manipulate the data, [b] populate web pages or templates, and [c] communicate with with a web server. I’d always approached Scoop and Slash, for example, as instances of the first kind: you have something you want to do, say, a forum. You want users to read stories and post comments. Editors have to have an interface behind the scenes to manage things. In the case of Scoop, blog engines, and other CMSs, you need to take user input, sanitize it, and save it. The “heavy lifting” with what I wanted to do was not at the interface layer … for the most part …; it was just doing the right queries. In a way what we wanted was a fancier phpMyAdmin or phpPgAdmin. In contrast Zope at the time felt monolithic, an all-in-one solution, not a toolbox, roll of tape, and jar of glue. My other area of familiarity was with OpenACS (via Philip and Alex’s Guide to Web Publishing, which got me thinking about these issues in the late 90s or so).
This is just a way of explaining [1] what I wanted/needed, [2] how I’d always thought about the problem because of what we were already famliar with, and [3] how I came to web frameworks in the first place. A framework came to mean a more unified version of LAMP, but the ‘P’ was less the language and more a set of libraries on/in the language, often making the ‘M’ more database-neutral. I’d have an ORM to abstract my database queries and, conveniently enough, a good deal of the business and presentation logic. Authentication and authorization might be taken care of for me as well; at the least internationalization and data-sanitizing would be covered, and so on. In particular, a roughly MVC web application framework covered, besides a scripting language: database access/abstraction, a templating language for producing web pages, a library for web forms, and a way of handling URLs. The framework often took care of sessions and some security aspects, it provided project or application scaffolding, and at the time there wasn’t much standardization on JavaScript/AJAX (libraries, hooks, etc.).
In the world of Python, 2007, there were three main framework options: Django, TurboGears, and Pylons. There were also a number of individual components—such as CherryPy—worthy of consideration. For me, though, it was a choice between Django and TurboGears. The latter attempted to be more tool-neutral. It was Python, but you could choose your ORM, your templating language, your web forms library, and what you wanted to use as a dispatcher. It might be SQLObject (later SQLAlchemy) as the ORM, Kid or Genshi for templating, CherryPy as the controller, and MochaKit for AJAX. In contrast TurboGears 2.x prefers SQLAlchemy, Genshi, Pylons, and Tosca Widgets. Django came across as more monolithic: it had its own ORM, its own templating language, its own web forms, and so on. It did not have a default AJAX library. “Philosophically” I preferred more minimalistic and less coupled tools, which meant I should have preferred TurboGears over Django, probably Pylons over TurboGears, and likely best of all a roll-your-own consisting of CherryPy and SQL Alchemy, possibly with a forms library as well.
III. Choosing
But Django had several things going for it, even in 2007 (after the magic-removal releases, I believe, but before 1.0). It was easy to install. I also found a hosting service—Webfaction—that supported it. It was no easier to install than Ruby or TurboGears (both also supported by Webfaction), but in addition it had a clear, easy-to-follow tutorial that got me into a usable if not terribly exciting sample project. Rails was pretty good here, too, but TurboGears less so. Django’s documentation was not perfect, but first of all it was clear and pretty well written, secondly it was rather extensive, and thirdly, because it was a monolithic framework, all the documentation was in one place. With TurboGears, in contrast, there was great documentation on all the parts, provided by the different parts, but the central TurboGears site was of less help. Around this time some Django-centric books were also published. At the time there was “This Week in Django” and similar podcasts and blogs.
This was not to last. “This Week in Django” went silent and then died. Cloud27, an early Pinax site (social networking software bundle built on Django), died. A number of bloggers and developers went on to other projects. Things change. There was a period, somewhat later, though, when I wondered whether I’d made the right choice.
But in the Django-TurboGears-Pylons-etc. consideration Django had a final ace up its sleeve: its killer admin app. Let me be clear: I have a love-hate relationship with the Django admin site/app, and even more of one with the ‘auth’ app, but if you’re throwing together a data-oriented site that non-techies will have to deal with, and there’s potentially a lot of CRUD (but not many actual ‘users’), then the Django admin gives you a solution ‘for free.’
This is, more or less, how I ended up choosing Django over TurboGears (and over Pylons and Rails) nearly five years ago. I can’t regret the decision at all, even if along the way I’ve come to gripe about various Django design decisions, such as:
- the design of the django.contrib.auth models (especially ‘User’)
- the ORM and its lack of support for composite keys
- the contenttypes framework
At the same time part of me wants to roll my own, ‘do it right,’ so to speak. Throw off the cruft.
I just have better things to do with my time right now.
- Previous: Language Choice