Reuse a block of code in several places in jinja2
Asked Answered
A

4

30

I have this html snippet which needs to be used in lots of places in the jinja2 templates:

<div class="usedalot">{{  somevalue }}</div>

for example, in template1.html, template2.html. template3.html, this code is repeated several places

<!-- template1.html, template2.html. template3.html -->
<div class="usedalot">{{  somevalue }}</div>
......
<div class="usedalot">{{  somevalue }}</div>
....
<div class="usedalot">{{  somevalue }}</div>
......

Instead of copying and pasting, is there someway to use this code snippet as a block? The jinja2 template inheritance (with blocks) do not seem to solve this problem.

Audwen answered 22/1, 2014 at 6:2 Comment(0)
A
58

What you are looking for is called a macro.

Macros are placed in separate files (e.g., macros.html).

{% macro usedalot(somevalue) %}
    <div class="usedalot">{{ somevalue }}</div>
{% endmacro %}

You can then import your macros in other templates

{% from 'macros.html' import usedalot %}

and then use them whenever needed

{{ usedalot(1) }}

This will output

<div class="usedalot">1</div>
Afterimage answered 22/1, 2014 at 6:31 Comment(3)
that's so incredibly ugly though. I mean it looks ok if your argument is 1. What if your argument is a BIG piece of HTML?Rotund
Why are you defining HTML inside a string literal in a template? That sounds like a code smell.Afterimage
no. I am telling, I don't want to do exactly that. The question is: how can I do it? see here #45113610Rotund
S
22

As of Jinja 2.8, you can also now use block assignments to map a block (still can only be defined once) to a variable that can be used multiple times in the document.

Documentation is at: Block assignments

I just used the feature to drop my HTML page title block into both the title element as well as the meta property for Facebook's opengraph:title attribute.

{% set title_s %}{% block title %}MY DEFAULT TITLE{% endblock %}{% endset %}
<head>
<meta property="og:title" content="{{ title_s }}" />
<title>{{ title_s }}</title>
...
</head>

This seems to me to be a much more clean solution than defining a macro.

Solemn answered 24/10, 2018 at 20:18 Comment(4)
This should be the accepted answer. Works great here in 2019 with Flask :)Lawrenson
This is a good solution. I don't believe the {% block title %} {% endblock %} is needed with block assignmentsRoulers
This is just using a variable in multiple places. I think James was after a reusable/parameterisable code block. Sth. like you can call like a function with variables.Hubing
exactly what I needed - simple and allows variables parametrization. I had to use a block inside it though to make it work, exactly like described.Hoard
A
1

Jinja's documentation today states:

If you want to print a block multiple times, you can, however, use the special self variable and call the block with that name:

<title>{% block title %}{% endblock %}</title>
<h1>{{ self.title() }}</h1>
{% block body %}{% endblock %}
Animato answered 6/4, 2023 at 13:7 Comment(0)
P
0

include is what I was looking for.

Example from docs:

{% include 'header.html' %}
Body goes here.
{% include 'footer.html' %}
Populate answered 28/3, 2024 at 4:17 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.