- 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)
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:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://purl.org/kid/ns#"
py:extends="'master.kid'">
<head>
<title> ${page.pagename} - 20 Minute Wiki </title>
</head>
<body>
<div class="main_content">
<div style="float:right; width: 10em">
Viewing <span py:replace="page.pagename">Page Name Goes Here</span>
<br/>
You can return to the <a href="/">FrontPage</a>.
</div>
<div py:replace="XML(data)">Page text goes here.</div>
<p><a href="${tg.url('/edit', pagename=page.pagename)}">Edit this page</a></p>
</div>
</body>
</html>
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