definiti" /> definiti" /> definiti"/>

Custom widgets: The equivalent of Mako's <%def> in Jinja2 or Django templates

135 Views Asked by At

I am quite proficient with Mako, but never actually used Jinja or Django templates.

What is Jinja/Django equivalent of Mako <%def name="..."> definition?

Following is a simplified example of my actual use case. I need to define a simple table and use it repeatedly on the page:

<%def name="temperature_table(north, east, south, west)">
    <table>
        <tr>
            <td>North:</td>
            <td>${north}</td>
        </tr>
        <tr>
            <td>East:</td>
            <td>${east}</td>
        </tr>
        <tr>
            <td>South:</td>
            <td>${south}</td>
        </tr>
        <tr>
            <td>West:</td>
            <td>${west}</td>
        </tr>
    </table>
</%def>

<h2>Morning</h2>
${weather_table(20, 21, 22, 23)}

<h2>Afternoon</h2>
${weather_table(22, 22, 25, 24)}

<h2>Night</h2>
${weather_table(17, 16, 17, 18)}

From what I gleaned from various articles, it could seem that blocks are used for this purpose in Jinja/Django. But blocks would introduce inheritance even to simple templates where a custom widget would be sufficient. Other authors suggest creating a custom tag, but, in my opinion, this would require to write custom parsing, rendering, and probably even custom cache managing functions. Am I missing something?

1

There are 1 best solutions below

0
β.εηοιτ.βε On BEST ANSWER

You can use a macro for that.

As described in the manual:

Macros are comparable with functions in regular programming languages. They are useful to put often used idioms into reusable functions to not repeat yourself (“DRY”).

Source: https://jinja.palletsprojects.com/en/3.0.x/templates/#macros

So, given:

{% macro weather_table(north, east, south, west) -%}
  <table>
      <tr>
          <td>North:</td>
          <td>{{ north }}</td>
      </tr>
      <tr>
          <td>East:</td>
          <td>{{ east }}</td>
      </tr>
      <tr>
          <td>South:</td>
          <td>{{ south }}</td>
      </tr>
      <tr>
          <td>West:</td>
          <td>{{ west }}</td>
      </tr>
  </table>
{%- endmacro %}

<h2>Morning</h2>
{{ weather_table(20, 21, 22, 23) }}

<h2>Afternoon</h2>
{{ weather_table(22, 22, 25, 24) }}

<h2>Night</h2>
{{ weather_table(17, 16, 17, 18) }}

It renders your expected tables.

<h2>Morning</h2>
<table>
  <tr>
    <td>North:</td>
    <td>20</td>
  </tr>
  <tr>
    <td>East:</td>
    <td>21</td>
  </tr>
  <tr>
    <td>South:</td>
    <td>22</td>
  </tr>
  <tr>
    <td>West:</td>
    <td>23</td>
  </tr>
</table>

<h2>Afternoon</h2>
<table>
  <tr>
    <td>North:</td>
    <td>22</td>
  </tr>
  <tr>
    <td>East:</td>
    <td>22</td>
  </tr>
  <tr>
    <td>South:</td>
    <td>25</td>
  </tr>
  <tr>
    <td>West:</td>
    <td>24</td>
  </tr>
</table>

<h2>Night</h2>
<table>
  <tr>
    <td>North:</td>
    <td>17</td>
  </tr>
  <tr>
    <td>East:</td>
    <td>16</td>
  </tr>
  <tr>
    <td>South:</td>
    <td>17</td>
  </tr>
  <tr>
    <td>West:</td>
    <td>18</td>
  </tr>
</table>