December 5, 2010

Templating Systems

Recently Danny Greenfeld wrote a blog post called Stupid Template Languages in which he attempted to advocate the Django approach to templating. Basically this is to keep any logic in the templates as simple as possible (but no simpler). So it includes the ability to write for loops but not, for example, to define re-usable procedures with parameter passing.

Armin Ronacher reacted to this with a blog post of his own called Not So Stupid Template Languages, in which he attempts to defend Mako and similarly complex templating schemes. I don't see the Jinja2 examples he gives as countering the main thrust of the Django wish for simplicity in templating. He does, however, explicitly point out the weaknesses of the Django include mechanism, and highlights the "macro" feature of Jinja2, which is its equivalent of Django's include feature. Jinja2 macros require that data is provided to the call by argument passing rather than simply being extracted from an implied context. I agree that requiring the use of arguments is probably a good way to make the couplings explicit.

This doesn't however, negate the value of keeping complex logic out of the templates. This desire originally comes from Django's background in the newspaper industry, where the designers were definitely not programmers. So they didn't need a hugely complex templating languages, and were prepared to ask the programmers to generate in their views the values required by the templates. I have worked with tools like Mako, which includes the ability to write very complex logic which should really be part of the controller rather than the view. It doesn't help that Django's designers perhaps didn't understand MVC that well, otherwise they would have called views "controllers" and templates "views". Nowadays I believe they call it the "model view template" model, but that still doesn't avoid the ambiguity about views and whether they should include logic or not.

Even with a pure MVC architecture Jinja2's argument-passing enhancements would be an improvement - as Armin says, making the couplings explicit would be a Pythonic thing to do. The nice thing is that argument passing could be implemented as a backwards-compatible extension, where a call without arguments could fall back to using the context as a default global namespace.


effbot said...

Well, the idea that the controller sits between the view and the model is a Java/Ruby thing, not an MVC thing.

(In the original design, the view pulls data from the model and renders it, while the controller interprets user events and updates the view and model accordingly. So for a readonly view, Django's view is an MVC view, using the template renderer and the browser as the presentation layer.)

Andreas said...

As far as I recall, the developers understood MVC perfectly, but just intentionally didn't apply it. It was only after years of kicking and screaming that they more or less accepted the MVC analogy.