haggholm: (Default)
[personal profile] haggholm

My website has gone through many, many iterations: Major backend changes are vastly more frequent than major content changes. For a while, I wrote some basic framework and generation stuff of my own, as a learning experience; more recently, I ported all the content to Django.

The only part of my website that makes real use of dynamic features is my book list, where I keep track of books I’ve read, and am starting to add features like automatically linking to Amazon, Chapters, Project Gutenberg, WorldCat, and so on; I’m also going to add my own personal ratings and reviews. (All, of course, because it pleases me to do so. I have no visitors to speak of.)

However, that book list—the only part that needed any tools at all beyond a menu preprocessor—was suffering from rather awful performance. The weak link turns out to be Django’s ORM. The list contains close to 700 books, correlated with authors, series (with volume information), languages, translations and translators… Of course, since pretty much all of the information is needed to display the page, it should be possible to fetch pretty much all the data in one query. Unfortunately, that’s not the case.

The page needs to fetch all Book objects. Ideally, the ORM would simply fetch all the related objects belonging to those books in the same query—Person and Language objects and so forth. Django, as far as I can tell, has no way of doing this automatically (by setting options or properties on the objects). It does expose a method to sort of do it, the select_related() method on the QuerySet…but it turns out to have a glaring weakness: It supports only simple foreign key relationships. There appears to be no way at all to invoke select_related() and fetch objects via many-to-many relationships! Since my database is full of those, this becomes a problem: The ORM made individual calls to fetch related data for each of almost 700 objects; a total of thousands of database calls per request—where only one call should be necessary!

Of course, I could easily make a custom query to present the list. However, after running up against the aforementioned obstacle with Django, I decided to have a look at TurboGears. The reason is twofold. First, since it’s the only part of my site that needs a framework at all, it does make sense to pick a framework that works well for that particular page. Second, it’s an excuse to explore a new framework—a learning experience. The latter alone is a sufficient reason to me; together, they were compelling.


Getting set up and porting my application to TurboGears was so trivial that it hardly bears speaking of. There was not much logic for most pages; setting up the URL and controller stuff was trivial. I do like the TurboGears style: Somehow it feels more natural than Django.

I first ported the templates from Django to Genshi; then, finding performance problematic, to Mako. I had some brief initial reservations about Mako. A template language that allows raw Python? My first thought was that it would invite worse practices, in that it allows a developer to put non-presentation code amidst presentation. However, in brief practice it felt helpful in that it allowed me to put some Python logic in the template that could not possibly be expressed in a Django template, but was really, truly not concerned with anything but the specific page’s presentation.

The most significant change is, of course, that TurboGears ships by default with SQLAlchemy, which is my poster child for what an ORM should look like. Using the declarative style, it’s simple to do simple things; but importantly, it allows you to accomplish whatever you damn well please. In particular, pulling in related objects—apparently impossible with the Django ORM—is trivial in SQLAlchemy (pass lazy='joined' to the relationship). Thus, loading my page requires one database query rather than thousands.

All is not rosy, however. I’m not enamoured with the style of Django’s documentation (I sometimes find it hard to locate what I need), but it is very comprehensive—and very accurate. With TurboGears, I’m a lot less impressed. I spent a lot of time following and reading information on Routes only to find, in the end, that support is limited and broken. Fortunately the default URL mapper gets me by, but I’m not entirely happy. Worse, following the documentation to customising the admin views, I have so far been unable to get anything working at all. When I followed the very examples from the docs, nothing happened at all!


At the moment, I have two very similar implementations of my site in Django and in TurboGears. The TurboGears version has a vast edge in performance: Generating the booklist page is about four times faster on initial load, and five times faster on subsequent access, before caching; accessing other pages, too, is much faster. On the other hand, the admin pages are currently not usable, so I have to rely on the Django admin views as they share the same DB. Annoying to be sure, though keeping the Django ORM definition up to date is not really a large maintenance burden to have a very slick admin interface.

I’m not very sure of where I want to go from here. The TurboGears version is faster; I prefer SQLAlchemy; and there are style aspects of TurboGears I prefer to Django. I like Mako in that I can put custom display stuff in defs in templates: In Django, where emphasis is placed on making templates presentation-only, I don’t have defs and so must place display-specific logic in separate files! On the other hand, Django seems a bigger and more reliable project, its documentation is superior—and TurboGears has some annoying glitches, as seen in my failure to get Routes and admin views to work (whether those failures are due to bugs proper, or inadequate/erroneous documentation)—and the deployment, though now safely automated, was just awful, with strange complaints of setuptools versions that were already in place.

I think I prefer TurboGears, but Django’s reliability, ease of deployment, and admin interface make me hesitate.

If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org

Profile

haggholm: (Default)
Petter Häggholm

July 2025

S M T W T F S
  12 345
6789101112
13141516171819
20212223242526
2728293031  

Most Popular Tags