I thought it would be interesting to write down why I chose TurboGears
over Django and Ruby on Rails as a sort of counterpoint Tabo's post
here:
http://tabo.aurealsys.com/archives/2005/10/11/django-or-why-i-chose-it-over-turbogears-and-ruby-on-rails/
I'll throw this up on the web eventually, but I was thinking maybe some
here could offer their own reasons for choosing TG.
As a bit of background, I first started developing database backed
websites in 1996 using Perl CGI scripts and Mini-SQL. I eventually
moved on to mod_perl, using Mason and Template-toolkit.
A couple of years ago I got into PHP, excited about a ubiquitous and
fast replacement for CGI scripts. PHP is a fairly terrible programming
language, but if you want to distribute web software it is great because
everyone already has it on their web server. I co-authored a book on
PHP and wrote countless lines of PHP but I often found myself working
around PHP's limitations rather than writing useful code. (And lets face
it, it is so much more fun to write code in Python than PHP)
Then at the beginning of this year I decided it was time to move on.
Time to learn something new. I decided to take a look at Java, Ruby and
Python. I would not have guessed I would end up picking Python, but I
fell in love with the clarity of the syntax and the lack of endless
magical functionality*.
Having decided on Python I was a little disappointed that it seemed very
few people were using it for web development. The web frameworks that
were available were really URL to function mappers with perhaps a
template language thrown in. Nothing wrong with that, just far from a
full web development stack. I ended up using a simple python server
pages implementation for templates, wrote my own ORM for Postgres and
used SCGI for the application server.
And things were good. Sometimes I wished for a Rails-style development
environment in Python and occasionally something similar would come
along, but nothing that really provided a compelling reason to switch
from my homegrown web-stack.
Then I heard about Django - I checked it out, but they were just
beginning to write the documentation and didn't have any videos (ooohhh
shiny webcasts!). Shortly after that Kevin Dangoor launched TurboGears
(and in a show of marketing shrewdness did the shiny webcast thing). I
decided to take a good look at both to see if I could ditch my homegrown
web stack for one and free up more of my time to write actual useful
code.
TurboGears was still very much getting off the ground and the Django
guys were starting to get a lot of the docs complete so I decided to try
out Django first (also Rob Curley's talk on IT conversations had piqued
my interest). I spent about a week playing with Django and reading
through much of the source code. I even submitted a couple patches.
More recently I have spent a few days with TurboGears.
I want to start with a bit of a disclaimer. Both projects are a large
leap forward in Python web frameworks. Both are managed by very capable
developers with strange last names (Django: Adrian Holovaty, TG: Kevin
Dangoor). Both are worthy choices for your web framework.
I'll break down this comparison into four parts:
1. ORM layer
2. URL mapping
3. Templating
4. Other Stuff
ORM Layers
TurboGears uses SQLObject and SQLObject is better. Django's ORM isn't
terrible, but SQLObject gets more things right. Using strings for
foreign key references between tables instead of the real class is a big
one. It makes setting up complex relationships between tables possible.
Some may prefer Django's syntax for doing selects over SQLObject's
sqlbuilder, but I personally prefer the more pythonic sqlbuilder.
(If you are blessed with only needing very simple models you may never
notice the limitations of Django's ORM in which case this becomes a much
closer comparison.)
URL Mapping
This one has to go to Django. The regexp-based url mapping makes it
easy to have beautiful, clean URLs in your app and to map them to any
arbitrary function. Things like:
http://www.example.com/blog/my_slug_here/
You can do this sort of thing in TurboGears, it just isn't as easy.
TurboGears uses CherryPy for a front end which really prefers options to
be specified in get variables like
http://www.example.com/blog?slug=my_slug_here
Templating
When it comes to templating, I think there are two camps. One, take the
full power of a programming language and make it available in your
templates. The other is to implement a templating language that barely
does anything other than variable interpolation and then slowly add
features to it until it becomes a programming language in it's own
right. TurboGears has chosen the former and Django has chosen the
latter.
TurboGears uses Kid which lets you write templates in XHTML with little
embedded python if statements and for loops. You can embed full python
functions in a template if you want to, but they can't output anything
directly and it isn't recommended.
You do get the full power of python in your if clauses and for loops
which means you can do any sort of arbitrary comparison that you need.
Things like:
<p py:if="system() == 'Linux'">
Good for you!
</p>
You can also define custom template functions and tags that act as
reusable blocks of HTML and kid can translate your XHTML code to HTML
4.0 for you - it is really quite flexible. The Kid language spec is
here:
http://kid.lesscode.org/language.html
Django uses their own template language which has a cool inheritance
feature. You can define your own tags that hook into the template
parser to add functionality. Django also implements a feature similar
to Template-Toolkit's Stash that allows you to use dots for method
calls, dictionary lookups, etc. So if you have
foo['bar'].baz()
You can call it from your template like:
{{ foo.bar.baz }}
Cool! They have some basic functions like an if statement, but it can
only check if a variable is true, no comparisons. So you can do
{% if foo %}
Wow foo is true.
{% endif %}
But you can't do
{% if foo > 5 %}
This doesn't work
{% endif %}
If you want to do a comparison, you have to use ifequal
{% ifequal foo bar %}
wow foo is equal to bar
{% endifequal %}
They also have ifnotequal and I suppose it is a matter of time before
someone implements ifgreaterthan, iflessthan and maybe even
ifgreaterthanorequalto, but this just seems silly to me.
If you are a big template minimalist you may prefer Django's approach,
but as soon as you want to do something slightly advanced like see if
one variable is greater than another your head is going to explode.
You could use another template system with Django, but a lot of the
things that make Django so nice like generic views and the built in
admin depend on the default template system.
Other Stuff
TurboGears is a bit newer. Django has a bit more thorough documentation
at the moment. TurboGears has built-in support for Ajax - you can use
the same controller methods for generating HTML and dumping out JSON.
Django has some features that are still in development on the TurboGears
side, notably a web interface to your model objects and full form
handling. But these things are not so hard to develop. The areas where
Django is lacking (ORM and templating) will not be as easy to fix.
It is true that TurboGears is made up of separate projects but I don't
think you can really "feel the glue" - maybe you can still smell it, but
it appears to be drying very quickly.
(*) When I was writing lots of Perl code I always had this vision of
Larry Wall and crew talking about Perl features like: "We must have a
magical loop variable" - "Yes, but what shall we call it?" - "Why $_ of
course! Unless it is an array, in which case it is @_!" - "Perfect!" I
should mention that I loved Perl and still have a certain fondness for
it and will leave all this Python nonsense behind the second Perl 6 is
done (just kidding ... we'll all be one big happy family on the Parrot
VM, right?!)
Sean Cazzell