I followed the Turbogears 20 minute tutorial here. The first impressions of Turbogears are:
- It's a bit more verbose than rails: there's more plumbing - you have to explicitly define which view you want to use for each action, as supposed to doing everything based on convention.
- you explicitly pass the local variables to the view as a hash, as supposed to using class or global variables
- Turbogears uses a template engine called kid by default, which is very different from rails' erb in philosophy, there's more emphesis on designer friendliness and higher level support for template inheritence
- Python/Turbogears in general is safer than ruby/rails - see my last post, in that you usually get more informative errors, such as NameError: global name 'pag' is not defined rather than nil when you didn't expect it
- The development feedback is not quite as good as rails. Turbogears requires a restart everytime you make a change. The restart is automatically triggered everytime you save a file in the project, and it is very fast, but it still takes about 5 seconds to rails' 0(ruby has this luxury because of its open classes)
I am hip to Haml so I had to see if I could get it working with Turbogears. I found a couple of implementations: ReML and GHRML. Tried them both, ReML was simpler and more approachable, so I wrote a Turbogears plugin for it. The important bit of the plugin code is here:
from reml import TemplateLoader
class RemlTg(object):
def __init__(self, extra_vars_func=None, options=None):
pass
def load_template(self, templatename):
"Find a template specified in python 'dot' notation."
parts = templatename.split('.')
return TemplateLoader('/'.join(parts[0:len(parts)-1])).load(parts[len(parts)-1] + '.reml')
def render(self, info, format="html", fragment=False, template=None):
"Renders the template to a string using the provided info."
return self.load_template(template).render(info)
After that, I converted the views in the tutorial into ReML. Let me do a wc on them for comparison, wait just a minute...
$ wc wiki20/templates/*.kid
25 76 1068 wiki20/templates/edit.kid
71 173 2802 wiki20/templates/master.kid
21 56 773 wiki20/templates/page.kid
21 50 705 wiki20/templates/pagelist.kid
138 355 5348 total
airport@wedding-singer ~/documents/play/turbogears/Wiki-20
$ wc wiki20/templates/*.reml
16 41 492 wiki20/templates/edit.reml
38 86 1338 wiki20/templates/master.reml
12 30 327 wiki20/templates/page.reml
8 24 190 wiki20/templates/pagelist.reml
74 181 2347 total
So that's about a 50% code reduction, not bad. Here's a Sample for comparison:
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
xmlns:py="http://purl.org/kid/ns#"
py:extends="'master.kid'">
page.reml
- append('master.reml')
- def title():
=page.pagename
- def content():
%div: 'style':'float:right; width: 10em'
Viewing
%span=page.pagename
You can return to the
%a: 'href':tg.url('/')
Frontpage
%div=unescaped(data)
%a: 'href':tg.url('/edit', pagename=page.pagename)
Edit this page