Mako or Jinja2?

35,936

Solution 1

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!

Solution 2

Take a look at wheezy.template example:

@require(user, items)
Welcome, @user.name!
@if items:
    @for i in items:
        @i.name: @i.price!s.
    @end
@else:
    No items found.
@end

It is optimized for performance (more here and here), well tested and documented.

Share:
35,936
ychaouche
Author by

ychaouche

Pythonista not using vista.

Updated on July 19, 2022

Comments

  • ychaouche
    ychaouche almost 2 years

    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 ?-

  • Jochen Ritzel
    Jochen Ritzel almost 14 years
    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.
  • Jesse Dhillon
    Jesse Dhillon almost 14 years
    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.
  • Sean Vieira
    Sean Vieira almost 14 years
    @Jesse -- to be fair, why not define and use a macro called makerow for the Jinja2 example? See: jinja.pocoo.org/2/documentation/templates#macros
  • Sean Vieira
    Sean Vieira almost 14 years
    Also, +1 for Jinja2 -- I too prefer its syntax.
  • Jesse Dhillon
    Jesse Dhillon almost 14 years
    I added the Jinja2 macros, thanks Sean.
  • Nikhil
    Nikhil almost 14 years
    @Jesse: I do not like Jinja2's insistence on (nearly) replicating Python. You can't use any built-in functions, including len and enumerate, unless you pass them in as context variables. And using .__len__ or loop.index0 instead is ugly and unintuitive.
  • Nikhil
    Nikhil almost 14 years
    Mako filters are simple - just use any function that you've defined or imported.
  • Nikhil
    Nikhil almost 14 years
    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.
  • Jesse Dhillon
    Jesse Dhillon almost 14 years
    @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).
  • zzzeek
    zzzeek over 13 years
    how can you compare jinja filters to mako filters, say they're "better", but "you've not seen" mako filters ? Seems hardly reasonable. We use practically the same syntax as Jinja for filters: ${user | get_name, default('No Name') , escape} . It's pretty obvious you've never used Mako which is perfectly fine but you're hardly in a position to make a reasonable comparison, or call our syntax "stupid", thanks for that !
  • Jesse Dhillon
    Jesse Dhillon over 13 years
    I wrote this a few months ago and I've since read up on Mako filtering syntax. I never called it stupid but I do question many of the design decisions made by the Mako team. In my opinion, Jinja was designed to be learned as quickly as possible, with the fewest documentation trips required. Mako was not, and it exhibits an arbitrary and inconsistent syntax. I am in a position to judge Mako, as I have used it; enough that I decided that it's not for me. PS, a quotation mark is used to quote words actually said. You imply that I said one is better or one is stupid, but I said neither.
  • Ib33X
    Ib33X over 12 years
    row {{ makerow(row) }} should be {{ make_row(row) }}
  • sayap
    sayap over 12 years
    @JesseDhillon: Actually, you did say "The example you provide is further proof that Mako suffers from syntactic stupidity". Anyway, as PyCharm is adding support for both Mako and Jinja2 in version 2.0, perhaps we should get the verdict on syntax complexity from their developers :D
  • Loïc Faure-Lacroix
    Loïc Faure-Lacroix over 11 years
    Did some edit to make the comparison match Jinja2. My guess is that mako is way more awesome. I mean, if you had jinja2 templates and want to convert to mako, you can make a precompiler that will understand jinja2 syntax and makes it work inside mako. By the way, mako syntax is more pythonic than jinja2.
  • nowox
    nowox about 6 years
    It looks nice, but the version available on pip is quite outdated: pypi.python.org/pypi/wheezy.template
  • Erik Aronesty
    Erik Aronesty about 5 years
    smx is the the smallest code base, easy to understand and extend: pypi.org/project/smx/0.8.4 %define(make_row, <tr> %for(name in row, <td>%name%</td> ) </tr> ) %set(body, <table> %for(row in rows, %makerow% ) </table> ) %expand(%include(base.html))