<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Posts about Turbogears</title>
    <link>http://wiki.futuretoby.com/tag/turbogears</link>
    <language>en-us</language>
    <item>
      <title>Impressions of Turbogears 4 months in</title>
      <description>I've been a user of Turbogears for 4 months now, working on a client facing app. The app has not gone production yet, so I don't have much insight on deployment, but I have a lot of experience on the development side - I started from scratch - and here is what I learned so far.&lt;br&gt;&lt;br&gt;&lt;b&gt;Freedom of Choice&lt;/b&gt;&lt;br&gt;Turbogears as a framework is pretty agnostic of different components such as ORM, or template engine. Although there is a default choice, I found it wasn't hard to stray away from it. &lt;br&gt;&lt;br&gt;&lt;b&gt;Mako&lt;/b&gt;&lt;br&gt;I ended up choosing Mako as the template engine because, coming from rails, I felt kid and genshi were too heavyweight for my taste since they are based on XSLT and requires your markup to be valid XML before it can do anything, which obviously means there's an XML parsing step it has to do. Mako is more like erb in that it's "text-based", e.i. it's perfectly fine to render non-valid XML code. But Mako turned out to be much more than another erb. With Mako you can easily write helper template functions and reuse them everywhere. You can also write inversion-of-control template style functions which take in a partial template and calls it inside its body. It always puzzled me why you couldn't do that with erb or haml or most of the ruby template engines easily. With erb, you have to write a partial view as a separate file, but calling a partial with local parameters is inconvient, you have to write something like:&lt;br&gt;&lt;br&gt;&lt;pre&gt;render :partial =&amp;gt; 'my_control', :locals =&amp;gt; {:control_id =&amp;gt; 'con', &lt;br&gt;    :height=&amp;gt; '50px'}&lt;/pre&gt;&lt;br&gt;and since this is so inconvient, i usually end up wrapping it with a helper method like:&lt;br&gt;&lt;br&gt;&lt;pre&gt;def my_control(control_id, height)&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; render :partial =&amp;gt; 'my_control', :locals =&amp;gt; {&lt;br&gt;        :control_id =&amp;gt; control_id, :height=&amp;gt; height}&lt;/pre&gt;&lt;pre&gt;end&lt;/pre&gt;&lt;br&gt;Of course this is partially due to the culture in rails that you normally write helpers in ruby rather than in a template language. In Mako you &lt;a href="http://www.makotemplates.org/docs/syntax.html#syntax_tags_def" mce_href="http://www.makotemplates.org/docs/syntax.html#syntax_tags_def"&gt;don't have to do this extra step&lt;/a&gt;, which makes me happy. Now if you want to do the inversion of control thing, in erb it's &lt;a href="http://www.igvita.com/2007/03/15/block-helpers-and-dry-views-in-rails/" mce_href="http://www.igvita.com/2007/03/15/block-helpers-and-dry-views-in-rails/"&gt;even worse&lt;/a&gt;! In mako you would just &lt;a href="http://www.makotemplates.org/docs/defs.html#defs_defswithcontent" mce_href="http://www.makotemplates.org/docs/defs.html#defs_defswithcontent"&gt;do this&lt;/a&gt;. So, in general, I am able to refactor my views a lot easier with mako and therefore I find myself doing it a lot more often.&lt;br&gt;&lt;br&gt;&lt;b&gt;SQLAlchemy&lt;/b&gt;&lt;br&gt;SQLAlchemy is a main stream ORM in the python community. It's direction is different from that of ActiveRecord and is a lot more similar to Hibernate of Java but also has similarities to Ambition of Ruby and Linq of .NET. It is similar to Hibernate in that it is very fully featured, has sessional transaction management, and can coupe with a large variety of schemas. It is similar to ambition and linq in that you can contruct queries in your host language in a very succint and elegant way(I know you can build queries in Hibernate's criteria API too, but it's not quite elegant). I like SQLAlchemy a lot! Here's a couple of sqlalchemy tricks I like. First one:&lt;br&gt;&lt;font face="courier new,courier"&gt;&lt;br&gt;&lt;/font&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fields = [&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User.user_name,&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User.display_name,&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User.email_address&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; results = User.query.filter(or_(*[f.ilike('%' + q + '%') &lt;br&gt;        for f in fields]))&lt;/pre&gt;&lt;br&gt;The above code does a wildcard partial string match of the string q against any of the three fields listed in the fields list. Second example:&lt;br&gt;&lt;br&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; page = User.query[10:20]&lt;/pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;This looks like array slicing, but no, it's slicing against the query results! It's smart enough to build the query using OFFSET and LIMIT or equivalent. You can easily do pagination with this technique.&lt;br&gt;&lt;br&gt;&lt;b&gt;Python's Named Parameters&lt;/b&gt;&lt;br&gt;Another thing I like when working with turbogears is python's &lt;a href="http://tobyho.com/parameter_list_chaining_in_python"&gt;named parameters&lt;/a&gt;. Whereas rubists use the hash as the poor man's name parameters, python has real named parameters, which is not only &lt;a href="/How_safe_is_your_programming_language" mce_href="/How_safe_is_your_programming_language"&gt;safer&lt;/a&gt;, but more elegant.&lt;br&gt;&lt;br&gt;&lt;b&gt;Python's Polluted Name Space&lt;/b&gt;&lt;br&gt;I run into this problem once in a while, but I hit on it 2 or 3 times in the last week! In python, &lt;i&gt;list&lt;/i&gt;, &lt;i&gt;dict&lt;/i&gt;, &lt;i&gt;str&lt;/i&gt;, &lt;i&gt;int&lt;/i&gt;, etc. are the names of fundamental types in the language, therefore you can't(actually you can, but don't want to) use them as variable names. More than once I've tried to use &lt;i&gt;list&lt;/i&gt; as a variable name, which python doesn't complain about immediately but causes a cryptic error down the road. &lt;br&gt;I've also tried use &lt;i&gt;from&lt;/i&gt; as a variable name, which turns out to be a keyword in the language, this causes a syntax error, which you don't see until you realize it's a keyword. Now, of course, more languages suffer from this problem, ruby isn't any different, but I think ruby has better error messages for these syntax errors: it will tell you the symbol that is unexpected and what symbols it was expecting.&lt;br&gt;&lt;br&gt;&lt;b&gt;Little Verbosity&lt;/b&gt;&lt;br&gt;Turbogears is more verbose than rails most prominently in 2 areas: import statements and method decorators. Rails files, usually have at most 2 requires(counterpart of import in python), most of the time none at all. My TG controller files and the model.py(the file with all the model objects) usually have about 10 to 15 lines of includes, my Mako template files usually 2 to 4 lines of includes. This has a lot to do with the design of the language. The python interpreter requires each .py file to act like a module, and as a module, it must identify all of its dependences, the ruby interpreter does not require this and so your controller code, for example, doesn't need to explicitly require anything before it has what it needs to do its work.&lt;br&gt;I think method decorators are cool, but they can also be overused and become cluttery. Some of my controller methods have more than 4 or 5 lines of decorators, consisting of the mandatory expose(), access restriction spec, and form parameter validators. That's a bit much. I also don't like the fact that you need an expose() decorator for every single controller method. Rails has no such thing and usually specifies such things at the top of the class, which has pros and cons vs TG's approach, but is at the end less cluttery.&lt;br&gt;&lt;br&gt;</description>
      <pubDate>Thu, 17 Jul 2008 22:53:02 -0500</pubDate>
      <guid>http://wiki.futuretoby.com/Impressions_of_Turbogears_4_months_in</guid>
      <author>toby ho</author>
      <link>http://wiki.futuretoby.com/Impressions_of_Turbogears_4_months_in</link>
    </item>
    <item>
      <title>Turbogears and ReML</title>
      <description>I followed the Turbogears 20 minute tutorial &lt;a href="http://docs.turbogears.org/1.0/Wiki20/Page1" mce_href="http://docs.turbogears.org/1.0/Wiki20/Page1"&gt;here&lt;/a&gt;. The first impressions of Turbogears are:&lt;br&gt;&lt;ol&gt;&lt;li&gt;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.&lt;br&gt;&lt;/li&gt;&lt;li&gt;you explicitly pass the local variables to the view as a hash, as supposed to using class or global variables&lt;/li&gt;&lt;li&gt;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&lt;/li&gt;&lt;li&gt;Python/Turbogears in general is safer than ruby/rails - &lt;a href="http://wiki.futuretoby.com/Ruby:%20Extremely%20Unsafe" mce_href="http://wiki.futuretoby.com/Ruby:%20Extremely%20Unsafe"&gt;see my last post&lt;/a&gt;, in that you usually get more informative errors, such as &lt;font color="#808080" face="courier new,courier"&gt;NameError: global name 'pag' is not defined&lt;/font&gt; rather than &lt;font color="#808080" face="courier new,courier"&gt;nil when you didn't expect it&lt;/font&gt;&lt;/li&gt;&lt;li&gt;The development feedback is not &lt;i&gt;quite &lt;/i&gt;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)&lt;br style=""&gt;&lt;/li&gt;&lt;/ol&gt;I am hip to Haml so I had to see if I could get it working with Turbogears. I found a couple of implementations: &lt;a href="http://reml.wikidot.com/documentation" mce_href="http://reml.wikidot.com/documentation"&gt;ReML&lt;/a&gt; and &lt;a href="http://lucumr.pocoo.org/cogitations/2008/02/15/ghrml-haml-for-genshi/" mce_href="http://lucumr.pocoo.org/cogitations/2008/02/15/ghrml-haml-for-genshi/"&gt;GHRML&lt;/a&gt;. Tried them both, ReML was simpler and more approachable, so I wrote a &lt;a href="http://docs.turbogears.org/1.0/TemplatePlugins" mce_href="http://docs.turbogears.org/1.0/TemplatePlugins"&gt;Turbogears plugin&lt;/a&gt; for it. The important bit of the plugin code is here:&lt;br&gt;&lt;br&gt;&lt;font color="#808080" face="courier new,courier"&gt;from reml import TemplateLoader&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="#808080" face="courier new,courier"&gt;class RemlTg(object):&lt;br&gt;&amp;nbsp; &lt;br&gt;&amp;nbsp; def __init__(self, extra_vars_func=None, options=None):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pass&lt;br&gt;&lt;br&gt;&amp;nbsp; def load_template(self, templatename):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Find a template specified in python 'dot' notation."&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parts = templatename.split('.')&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return TemplateLoader('/'.join(parts[0:len(parts)-1])).load(parts[len(parts)-1] + '.reml')&lt;br&gt;&lt;br&gt;&amp;nbsp; def render(self, info, format="html", fragment=False, template=None):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Renders the template to a string using the provided info."&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self.load_template(template).render(info)&lt;/font&gt;&lt;br&gt;&lt;br&gt;After that, I converted the views in the tutorial into ReML. Let me do a wc on them for comparison, wait just a minute...&lt;br&gt;&lt;br&gt;&lt;font color="#808080" face="courier new,courier"&gt;$ wc wiki20/templates/*.kid&lt;br&gt;&amp;nbsp; 25&amp;nbsp;&amp;nbsp; 76 1068 wiki20/templates/edit.kid&lt;br&gt;&amp;nbsp; 71&amp;nbsp; 173 2802 wiki20/templates/master.kid&lt;br&gt;&amp;nbsp; 21&amp;nbsp;&amp;nbsp; 56&amp;nbsp; 773 wiki20/templates/page.kid&lt;br&gt;&amp;nbsp; 21&amp;nbsp;&amp;nbsp; 50&amp;nbsp; 705 wiki20/templates/pagelist.kid&lt;br&gt;&amp;nbsp;138&amp;nbsp; 355 5348 total&lt;br&gt;airport@wedding-singer ~/documents/play/turbogears/Wiki-20&lt;br&gt;$ wc wiki20/templates/*.reml&lt;br&gt;&amp;nbsp; 16&amp;nbsp;&amp;nbsp; 41&amp;nbsp; 492 wiki20/templates/edit.reml&lt;br&gt;&amp;nbsp; 38&amp;nbsp;&amp;nbsp; 86 1338 wiki20/templates/master.reml&lt;br&gt;&amp;nbsp; 12&amp;nbsp;&amp;nbsp; 30&amp;nbsp; 327 wiki20/templates/page.reml&lt;br&gt;&amp;nbsp;&amp;nbsp; 8&amp;nbsp;&amp;nbsp; 24&amp;nbsp; 190 wiki20/templates/pagelist.reml&lt;br&gt;&amp;nbsp; 74&amp;nbsp; 181 2347 total&lt;/font&gt;&lt;br&gt;&lt;br&gt;So that's about a 50% code reduction, not bad. Here's a Sample for comparison:&lt;br&gt;&lt;br&gt;&lt;b&gt;page.kid:&lt;/b&gt;&lt;br&gt;&lt;font color="#808080" face="courier new,courier"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:py="http://purl.org/kid/ns#"&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; py:extends="'master.kid'"&amp;gt;&lt;br&gt;&amp;lt;head&amp;gt;&lt;br&gt;&amp;lt;title&amp;gt; ${page.pagename} - 20 Minute Wiki &amp;lt;/title&amp;gt;&lt;br&gt;&amp;lt;/head&amp;gt;&lt;br&gt;&amp;lt;body&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div class="main_content"&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div style="float:right; width: 10em"&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Viewing &amp;lt;span py:replace="page.pagename"&amp;gt;Page Name Goes Here&amp;lt;/span&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;br/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; You can return to the &amp;lt;a href="/"&amp;gt;FrontPage&amp;lt;/a&amp;gt;.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div py:replace="XML(data)"&amp;gt;Page text goes here.&amp;lt;/div&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;p&amp;gt;&amp;lt;a href="${tg.url('/edit', pagename=page.pagename)}"&amp;gt;Edit this page&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;/body&amp;gt;&lt;br&gt;&amp;lt;/html&amp;gt;&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;page.reml&lt;/b&gt;&lt;br&gt;&lt;font face="courier new,courier"&gt;&lt;font color="#808080"&gt;- append('master.reml')&lt;br&gt;- def title():&lt;br&gt;&amp;nbsp; =page.pagename&lt;br&gt;- def content():&lt;br&gt;&amp;nbsp; %div: 'style':'float:right; width: 10em'&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Viewing&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; %span=page.pagename&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; You can return to the&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; %a: 'href':tg.url('/')&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Frontpage&lt;br&gt;&amp;nbsp; %div=unescaped(data)&lt;br&gt;&amp;nbsp; %a: 'href':tg.url('/edit', pagename=page.pagename)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Edit this page&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;br&gt;&lt;/font&gt;</description>
      <pubDate>Thu, 20 Mar 2008 10:10:00 -0500</pubDate>
      <guid>http://wiki.futuretoby.com/Turbogears_and_ReML</guid>
      <author>toby ho</author>
      <link>http://wiki.futuretoby.com/Turbogears_and_ReML</link>
    </item>
  </channel>
</rss>

