Python Template languages (Part 1 — Django)

I’ve been thinking a lot about template engines in Python recently. Partly because sourceforge.net’s new python code needed to choose a template language, and there were some questions about why we would choose one over the others.

But beyond that In the past few weeks used Genshi, Mako, Jinja, Django Templates, and Cheetah, and have been looking at, but not yet using out chameleon.genshi.

I figure all this promiscuous template library usage means that I should put my thoughts down somewhere. There are advantages and disadvantages of all these libraries, but I think that the choices are pretty clear once you know your constraints.

I’m not going to commit to covering them all in depth, but I’m going to try to put my thoughts about them down over the next few days.

For today let’s talk about the pros and cons of Django Templates. This is another post that has been developed over the last year or so, where typed stuff up while working on fossfor.us.

Django made making fossfor.us easy in lots of ways. Want threaded comments? Add the existing app in a couple hours — Done! Want OpenID? Again add an app — Done!

But it also had frustrations, and one of the biggest for me was the template language.

First the good

Django templates operate in a sandboxed environment. This is good because it limits the ways that designers can blow-up your web-app. In fact this seems to be an underlying design decision of the Django framework. It’s the reason accessing non-existent variables just returns empty strings, because as the Djanogo book tells me “you wouldn’t want a designer to be able to take down your website with a typo.”

I can respect that, and I definitely see the benefits of sandboxing template code, particularly in places where end-users might be allowed to edit templates.

Easy to learn, and easy to use
They also provide a very simple syntax, that’s very well documented. This makes it easy for designers to figure out.

All of this is good.

But there are some negatives

Django developers seem to love them, but I feel like there are some significant drawbacks to using django templates.

Not trivial to use outside of django.

You can do it, but it’s not easy, and you end up with a lot of Django loaded that you don’t need. Fortunately there’s Jinja which is somewhat Django template like, but which isn’t at all dependent on Django itself. So, if you’re not using Django, I think it’s sane to recommend that you use Jinja templates. And tomorrow I’ll blog more about why I think that Jinja is just a better version of Django templates.

Won’t let you follow the fail early philosophy of development

When you use Django Templates in Django, I have two major issues. THe first is the decision to always treat undefined variables as variables that contain an empty string. Generally “fail fast” is a good engineering principle, because it’s helps you find problems sooner, and makes debugging much easier.

Of course the Django guys are smart, and the knew about this so they planned for it.

Well sort-of, apparently it’s easy enough to make invalid variables return something other than an empty string by setting the TEMPLATE_STRING_IF_INVALID config variable to something else, which gets displayed if you access an undefined variable in a template (say you make a typo. And this does makes it easier to find template errorsmore quickly.

But it’s not really “failing fast.”

I want an all out failure, not a small difference in the rendered page.

With that said, this as faar as it goes, I think it is good. TEMPLATE_STRING_IF_INVALID should be a configuraiton option, (though perhaps with a better name) and people should turn it on in development and off in production. Pylons does this with it’s c variable, and I think it’s very helpful.

But what I want is the exception, not just some random other text inserted, so then I looked into what it would take to force django template rendering to stop silently suppressing exceptions, and it’s not that hard on first glance.

The template renderer depends on a special attribute silent_variable_failure being set to True on the exception, so all we would have to do is just disable this checking when the fail_fast config value was set to True and we’d be good to go.

Seemed like a good idea, but in reality — not so good.

Django’s admin will totally break if you do such a thing, and it turns out that even setting the TEMPLATE_STRING_IF_INVALID parameter makes these pages render quite badly.

I ultimately found this tidbit in the Django Template Docs:

While TEMPLATE_STRING_IF_INVALID can be a useful debugging tool, it is a bad idea to turn it on as a ‘development default’.

Many templates, including those in the Admin site, rely upon the silence of the template system when a non-existent variable is encountered. If you assign a value other than ” to TEMPLATE_STRING_IF_INVALID, you will experience rendering problems with these templates and sites.

Generally, TEMPLATE_STRING_IF_INVALID should only be enabled in order to debug a specific template problem, then cleared once debugging is complete

Oops, that’s exactly what I don’t want. In practice this was not as bad as I thought it would be, but it was not good, and it made my life harder because the time between making a typo in a template and finding the problem increased, which also increased the dificulty of finding the cause of the problem.

My other frustration with Django Templates

Beyond that, the fact that Django template sandboxing excludes all expressions pushes lots and lots of work into filters and up into the “views” which other frameworks call “controllers” and means that django views mix presentation and action logic even more than is common in other MVC like web frameworks (Rails, Pylons, TurboGears, etc.).

Having a full featured experssion language like python in templates has been very useful to me in capturing presentation logic in the template.

And at the same time creating anything like a “macro” or a “template function” (a bit of reusable template code) requires some slightly complicated python gymnastics.

I’m certainly no MVC purist, but I think that in the new post web-2.0 world where applications have HTLM frontends, rich javascript front-ends, and even flex/silverlight clients, it makes a lot of sense to keep presentation logic out of the “view/controller” and let that focus on handling HTTP requests, and marshaling the data required by whatever presentation technology (html, html+javascript, flex, rich-client + JSON, or whatever) you happen to use.

And I really want to be able to have code-reuse in templates without jumping through hoops. That’s part of what a template language is for, so I really don’t like giving it up.

Conclusion

With all of that said, if the benifits of Django (reusable apps mainly) are important to your project, you should use Django, and if you are using Django you absolutely should use Dango Templates. They aren’t bad really. It’s just that I’m used to the other options that do it better.

So, ultimately if you’re not already using Django, I think you should consider one of the other options, as I think they all do better on template code reuse, and allowing fail fast behavior.

More Soon

Tomorrow I’ll try to write a bit more about Jinja, but I think this post pretty much sumarizes why I think that Django Template users outside Django proper should really just use Jinja2.

9 Responses to “Python Template languages (Part 1 — Django)”


  1. Generally I do think custom tags are the answer for more complex presentational logic (and a few other things as well). But you’re right in that writing them sucks. Part of it is just the way the template system works — first you parse (and so have to tell the system how to parse your tag) and then you render (and so have to tell it how to render). And I’d dearly love to get proper namespaces in there at some point.

    But I also think we’ve failed pretty hard on that area of the documentation, because there are some fairly powerful patterns that crop up in real-world applications, but which aren’t mentioned at all in the docs (sometime have a look at the tags in contrib.comments for an example — they lets you write an awful lot of custom functionality with very little code). One of these days when I have free time again I’ll see what I can do to expand the coverage and make it a bit more approachable, since overall it’s really not that hard, just something we really don’t help people understand right now.

    As for logic in templates, well, I do tend to agree with Jacob (http://jacobian.org/writing/salt/) — I’d rather add a bit of salt now and again than have to worry about too much already being baked in :)

  2. 2Antoine

    I guess the advent of cheesy download sites means Linux has become a true mainstream platform :)

  3. 3Bob

    Would it be hard to change the code to support early failure better?

    From what I have read it looks like a (somewhat) minor fix, but for some developers it would be a great gain.

  4. James,

    I love the salt analogy.

    But the thing with template languages is that features aren’t “baked in” until you use them. Jingja, Genshi, and Mako all *allow* you to add lots and lots of salt to your templates, to the point where they are absolutely unusable by designers. But they don’t *require* you to add salt.

    Meanwhile Django Templates require you to jump through hoops if you want even a little bit of extra salt.

    That said, there are people who *should* have the salt taken away from them. I had a college roommate who put 1/2 cup of vanilla in some ground beef that he was planning to turn into lasagna. After that we wouldn’t let him near the spice drawer… ;)

  5. Mark, for me at least it’s a theory of wanting to start with the simplest (i.e., least amount of logic) that could work for a significant number of people, then selectively adding more “salt” as good use cases come up. Which, really, is how Django’s template language has been evolving; quite a few of the most useful tags were added around the 1.0 push, when we had a good solid base out there to understand what people were really missing.

  6. I don’t have enough practical experience with Django
    templates to add anything meaningful to the conversation.

    My experience is with Cheetah, which I tend to hook into the framework early on. The Django work I’ve done ends up being mostly Cheetah with some Django templates in place where it’s easier. Unfortunately I’m not dealing with designers writing pages.

    I did want to say it was a great article, and I look forward to the rest of your series. Thanks.

  7. 7Tom Swirly

    What about Clearsilver? I used it successfully for a templating project at my last job and it worked very well with Python…

  8. I too like the salt analogy, and I think this development cycle for Django is proving why that works. Django’s template engine basically started as the least logic humanly possible to do design. However, this release of Django adds a more expressive syntax to the {% if %} tag, which is turns out is really handy for design logic. I do however prefer the approach of using templatetags for anything more complicated than this. You and James both pointed out they are *way* too hard to write, but I think that’s being addressed by projects like templatetag-sugar (mine), tagcon, or surlex.

  9. 9Jacob

    I don’t think it is decidable in the abstract whether a “salt umbrella” is good or bad in general. But for a particular set of site authors and maintainers, it may be clearly decidable. My team stopped using django templates with django some time ago, because the template authors and the programmers are the same people, and hence there is no group of less experienced webmonkeys who need the protection of a sandboxed language (a language, incidentally, which is in some respects more intricate and harder to learn, while being less capable, than an uncrippled language like Python); and the cost of having to write a tag whenever you want to do almost anything besides interpolate just became silly. So we’re using mako, even with reusable apps from other sources (this is quite possible, via our django-smorgasbord app), and although mako syntax is in some respects less pretty than django’s, it has been a big hit.

    I should stress this: Mark, you say that if you are using django you absolutely should use django templates — but in my experience there has been no penalty to swapping them out with mako — zero.

Comments are currently closed.