Turbogears and ReML

I followed the Turbogears 20 minute tutorial here. The first impressions of Turbogears are:

  1. 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.
  2. you explicitly pass the local variables to the view as a hash, as supposed to using class or global variables
  3. 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
  4. 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
  5. 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:

page.kid:


          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      xmlns:py="http://purl.org/kid/ns#"
      py:extends="'master.kid'">

${page.pagename} - 20 Minute Wiki


   


       

            Viewing Page Name Goes Here
           

            You can return to the FrontPage.
       


       
Page text goes here.

       

Edit this page



   




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


blog comments powered by Disqus