fork me on github

my experience with mako

    follow me on Twitter
    Oct 13 2009 at 1:56 pm

    I used mako for this blog's templates primarily because I hadn't ever used mako for anything and I was curious. I have used cheetah and django templates pretty extensively, and so after rolling jinja in with django and discarding anything XML-based, mako is pretty much the only major python-based templating system I don't yet know.

    In my experience templating engines pretty well fall into two philosophical camps - those that want to expose a full-featured language, and those that intentionally restrict the power of the template code to enforce separation of concerns. When it comes to web frameworks I definitely throw my hat in with the latter crowd, having seen too many cases of a powerful templating language being used for model, controller and view code all in one. I think that django strikes the right mix of a templating language which is limited to display logic out-of-the-box, but which is also extensible and exposes lower-level machinery so you can break that paradigm if you want, but you have to really want to.

    For this project which only uses the server to serve static content, I wanted the template to be essentially the lowest level in the stack (there is only a very thin controller layer), and therefore wanted powerful templates. The thing I dislike about cheetah the most is that if that power is going to be exposed, I shouldn't have to prefix every code statement with a special character (#), or use extra keywords for things like assigning to variables (set). It makes scripting code feel very second-class. The PHP-esque <%...%> python blocks of mako look really appealing now. As the mako homepage says, "Python is a great scripting language. Don't reinvent the wheel...your templates can handle it!"

    Unfortunately, mako seems to have some serious problems of its own. One is syntax overload. You have simple expression escaping with the familiar ${...} notation, python blocks with <% ... %>, module-level python blocks with <%! ... %>, a myriad of xml-ish tags like <%include>...</%include> (srsly?), and finally cheetah-style inline statements, prefixed with %. What is the deal? Django has 2 pieces of syntax: {% tag %}...{% endtag %} and {{ variable }}. Cheetah also has two: ${...} (with curly-braces optional) and line-leading # for statements. This is a big problem, mako.

    Another issue issue I have had seems to have significant overlap with a pattern that I would imagine to be a major use-case. There is no way to store a variable in a global namespace from a parent template and have it visible in the child (I am ready to be corrected on this point, I just couldn't find one).

    My problem is that I have an embed from twitter for which I need to place a <div> in the right place in the markup, and a <script> at the end of the body. What I'd like to do is expose a function from the base template that embeds the <div> and sets a global (really render-wide) variable, so that in the parent's body it can know that the <div> is there and include the <script>. Instead I'm having to expose two functions, twitter_embed() and twitter_js(), and call them both in the right places in the child. Adam Gomaa explains the issues here pretty well. In contrast, cheetah's inheritance simply maps straight onto python class inheritance. Django doesn't allow setting variables from within templates by default, but the way you would do it with a custom tag would be to apply it to the context, which is render-wide, so would make it up to parents and down to children.

    So in the end, I think that if I had to do this same project again I would probably use Cheetah, and not just because I work with the maintainer (for a little while longer, at least). I think most web code out there should be following the practices that allow the django/jinja approach and that's still my favorite templating language, but there are definitely use-cases for powerful templates, and coming from python there's just too many surprises in mako.

    blog comments powered by Disqus