views:

372

answers:

2
+2  Q: 

Mako or Jinja2 ?

I didn't find a good comparison of jinja2 and Mako. What would you use for what tasks ?

I personnaly was satisfied by mako (in a pylons web app context) but am curious to know if jinja2 has some nice features/improvements that mako doesn't ? -or maybe downsides ?-

+9  A: 

I personally prefer Jinja2's syntax over Mako's. Take this example from the Mako website

<%inherit file="base.html"/>
<%
    rows = [[v for v in range(0,10)] for row in range(0,10)]
%>
<table>
    % for row in rows:
        ${makerow(row)}
    % endfor
</table>

<%def name="makerow(row)">
    <tr>
    % for name in row:
        <td>${name}</td>\
    % endfor
    </tr>
</%def>

There are so many constructs here that I would have to consult the documentation before I could even begin. Which tags begin like <% and close with />? Which of those are allowed to close with %>? Why is there yet another way to enter the template language when I want to output a variable (${foo})? What's with this faux XML where some directives close like tags and have attributes?

This is the equivalent example in Jinja2:

{% extends "base.html" %}

<table>
  {% for row in rows %}
    {{ makerow(row) }}
  {% endfor %}
</table>

{% macro make_row(row) %}
  <tr>
    {% for name in row %}
      <td>{{ name }}</td>    
    {% endfor %}
  </tr>
{% endmacro %}

Jinja2 has filters, which I'm told Mako also has but I've not seen them. Filter functions don't act like regular functions, they take an implicit first parameter of the value being filtered. Thus in Mako you might write:

${escape(default(get_name(user), "No Name"))}

That's horrible. In Jinja2 you would write:

{{ user | get_name | default('No Name') | escape }}

In my opinion, the Jinja2 examples are exceedingly more readable. Jinja2's more regular, in that tags begin and end in a predictable way, either with {% %} for processing and control directives, or {{ }} for outputting variables.

But these are all personal preferences. I don't know of one more substantial reason to pick Jinja2 over Mako or vice-versa. And Pylons is great enough that you can use either!

Update included Jinja2 macros. Although contrived in any case, in my opinion the Jinja2 example is easier to read and understand. Mako's guiding philosophy is "Python is a great scripting language. Don't reinvent the wheel...your templates can handle it!" But Jinja2's macros (the entire language, actually) look more like Python that Mako does!

Jesse Dhillon
Not really fair: Your "equivalent in Jinja" excluded half the stuff from the Mako example and thus looks shorter. Mako's `<% />` vs `<% %>` is not that confusing (blocks vs inline code). Mako has filter functions too and they look just the same.
THC4k
I said these are matters of personal preference, you are free to show how Mako's syntax makes more sense to you. I didn't include the definition of makerow because that's not part of a template in Jinja.
Jesse Dhillon
@Jesse -- to be fair, why not define and use a macro called `makerow` for the Jinja2 example? **See:** http://jinja.pocoo.org/2/documentation/templates#macros
Sean Vieira
Also, +1 for Jinja2 -- I too prefer its syntax.
Sean Vieira
I added the Jinja2 macros, thanks Sean.
Jesse Dhillon
@Jesse: I do *not* like Jinja2's insistence on (nearly) replicating Python. You can't use any [built-in functions](http://docs.python.org/library/functions.html), including `len` and `enumerate`, unless you pass them in as context variables. And using `.__len__` or `loop.index0` instead is ugly and unintuitive.
Nikhil Chelliah
Mako filters are simple - just use any function that you've defined or imported.
Nikhil Chelliah
However, I agree that Jinja2 is generally cleaner, more customizable (e.g. you can change the syntax), and in my experience more forgiving regarding Unicode.
Nikhil Chelliah
@Nikhil, agreed re: `loop.index0` business. Not sure why having to specifically import built-ins into the environment matters: it's a one-line declaration to add the ones which matter to you one-by-one. Although I do frequently get confused by whether I should be using `true` or `True` in a given situation, which is dumb (I think it doesn't matter).
Jesse Dhillon
A: 

Jinja2 has filters, which I'm told Mako also has but I've not seen them.

Searching for mako filter would have answered your question by sending you to the relevant page of the Mako documentation.

Mako filters are similar to Jinja's in that they take a default parameter of whatever value the preceding expression take, but different in that they're comma-separated with a single pipe between expression and filters: {{ foo | bar | baz }} becomes ${foo | bar, baz}.

You will note that I didn't reuse your example. That is because Mako expressions contain arbitrary Python expressions, so instead of having to go through 2 different filters to retrieve a user, you'd probably just have a get_name(default=None) method on your user and you'd write ${ user.get_name(default='No Name') } (autoescaping is enabled by default in Mako templates, but if you'd disabled it you'd add the h html-escaping filter)

Masklinn
I wasn't asking whether or not they exist or how to use them. I was stating that I haven't seen them, and I didn't care to discuss them any further. The example you provide is further proof that Mako suffers from syntactic stupidity.
Jesse Dhillon