Open In App

How to use Macros in Jinja

Last Updated : 04 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Macros are a powerful functionality provided by Jinja, a text rendering engine for Python programming language. Macros in Jinja are similar to functions in other programming languages and help to implement the DRY Principle of programming (i.e., Don’t Repeat Yourself) in the Jinja templates by helping to avoid repeated code. It is fairly easy to use macros. This article intends to show how to use macros in Jinja. It assumes basic familiarity with Python programming language and Jinja.

What is Jinja?

Jinja is a text rendering engine for Python programming language. Armin Ronacher created it and is available under a BSD software licence. It has first-class support among popular Python frameworks like Django and Flask and is used extensively. It is popular for its easy and straightforward syntax and variety of features including (but not limited to) –

  • Variable access.
  • Control structures (Conditionals, loops).
  • Macros (similar to functions in programming languages).
  • Filters
  • Inheritance, etc.

Its syntax is heavily influenced by Django and Python which is good for anyone already familiar with Python.

What are Macros in Jinja?

Macros in Jinja are similar to functions in other programming languages. They are used to encapsulate logic used to perform repeatable actions. Macros can take arguments or be used without them. Inside macros, we can use any of the Jinja features and constructs. The result of running a macro is some text. In other words, wherever we call a macro inside the template, it is replaced with the string/text resulting from calling the macro.

We can create reusable components of the code and then use them at multiple places by just calling the macro. We can even save a macro or a collection of macros in a separate Jinja file and then import the file into multiple other jinja files where we wish to use those macros. This is useful when we want to make changes. In case we use macros, we just have to modify the macro to implement the changes, otherwise, one would need to modify every place where the logic is explicitly written.

Syntax to create/define Macros in Jinja

{% macro macro_name(*args, **kwargs) %}
< macro body >
{% endmacro %}

Start defining the macro with

{% macro macro_name(*args, **kwargs) %}

where “macro_name” is replaced with the name of the macro, *args is replaced with positional arguments of the macro (if any) and **kwargs is replaced with the keyword arguments of the macro. This is almost similar to python’s function defining syntax. Next, define the body of the macro which is normal Jinja syntax. Finally place the text “{% endmacro %}” where the body of the macro ends.

Calling Macros in Jinja

We can call the macro by its name inside the “{{ <expression goes here> }}” delimiter. For example, to call the macro named “macro_name”, we can write the following syntax at the place in jinja template file where we want its output text –

{{ macro_name() }}

If it takes some arguments, we can also pass these inside the parentheses like this –

{{ macro_name(arg1, arg2, ...., kwarg1 = value1, kwarg2 = value2, ...) }}

where argn represents nth positional argument and kwargn represents nth keyword argument. Both these are analogous to python’s positional and keyword arguments.

A Jinja Macro Without any Arguments

This section shows how to create a basic macro without any arguments. The macro just renders the string “Hello World” wherever it is called. Create a file named “helloMacro.jinja” in “templates” folder and a file named “helloMacro.py” in “jinjaTests” folder. “helloMacro.py” file will be used to render “helloMacro.jinja” template and print the rendered text to the screen. Here are the contents of “helloMacro.jinja” file –

helloMacro.jinja

{% macro hello() %}
Hello rendered from the macro hello().
{% endmacro %}
Some text rendered using a macro: {{hello()}}

First we define the macro named hello with empty parentheses since it accepts no arguments. Then we have some text in its body and we finally end it with the “{% endMacro %}” line as stated earlier. Next we call it in the last line as “hello()” inside the “{{ }}” delimiter as stated earlier.

Example

It is loading “helloMacro.jinja” file as template

Python3




from jinja2 import Environment, FileSystemLoader
env = Environment(loader = FileSystemLoader('templates'))
template = env.get_template('helloMacro.jinja')
output = template.render()
print(output)


Run the above file from the “jinjaTests” folder .

Output


Some text rendered using a macro:
Hello rendered from the macro hello().

A Jinja Macro with Arguments

This section shows how to create a basic macro with arguments. Create a file named “helloArgMacro.jinja” in “templates” folder and “helloArgMacro.py” in “jinjaTests” folder. The later one will be used to render the former template. Here are the contents of “helloArgMacro.jinja” file –

helloArgMacro.jinja

{% macro helloName(a,b,name = "no name") %}
Hello {{name}}.
Sum of {{a}} and {{b}} = {{a+b}}.
{% endmacro %}
Result of running the macro: {{helloName(1,2,name = "Geek")}}

Everything is same as the last example except that we are handling arguments: two positional arguments a and b and one keyword argument name. While defining the macro named helloName we defined these arguments inside parentheses as seen in the first line. We can access these arguments inside the macro-body and utilize them. Similarly, while calling helloName macro, we pass the values of these arguments. Remember this is very similar to Python arguments. We can even omit the values of keyword arguments in which case the default argument (here “no name” is the default) will be used. Here are the contents of “helloArgMacro.py” file –

We load the “helloArgMacro.jinja” file as template and render it.

Python3




from jinja2 import Environment, FileSystemLoader
env = Environment(loader = FileSystemLoader('templates'))
template = env.get_template('helloArgMacro.jinja')
output = template.render()
print(output)


Run the above file to see the output text on the screen.

Output

Result of running the macro:
Hello Geek.
Sum of 1 and 2 = 3.

If we remove the name argument while calling, we will get the output with the default value for name –

Output

Result of running the macro:
Hello no name.
Sum of 1 and 2 = 3.

Advanced examples of using Jinja Macros

In bigger projects, it is often convenient to keep functions in separate files and then import and call them in files wherever needed. We can do the same with macros too. We can define the macros in separate jinja file(s) and import one or more of these files as per requirement in any file to use the macros.

Example: Keeping Jinja macros in separate file(s)

Create a file named “myMacroCollection.jinja” inside “templates” folder. This will contain our macros. Create a file named “importExampleTemplate.jinja” inside “templates” folder. This file will import and call macros from “myMacroCollection” file. Create a file named “importExampleTemplate.py” inside “jinjaTests” folder. This will render and show the output of “importExampleTemplate.jinja” template on screen.

Add this first macro to “myMacroCollection.jinja” file –

{%macro hello() %}
{# This macro just renders string Hello #}
Hello!
{%endmacro%}

Now here are the contents of the “importExampleTemplate.jinja” file –

{% import 'myMacroCollection.jinja' as mmc %}
{{mmc.hello()}}

We use the jinja import syntax to import the “myMacroCollection.jinja” file in “importExampleTemplate.jinja” file with the alias name mmc. Now we can access all the macros inside mmc with the syntax –

mmc.<macro-name>(<arguments>)

Note how similar this system is to python import syntax. Here are the contents of “importExampleTemplate.py” file which is used to render the “importExampleTemplate.jinja” file and print the output string on the screen –

Python3




from jinja2 import Environment, FileSystemLoader
env = Environment(loader = FileSystemLoader('templates'))
template = env.get_template('importExampleTemplate.jinja')
output = template.render()
print(output)


Output:

Hello!

Conclusion

Jinja is a powerful and popular text rendering engine for Python programming language. It is highly used and integrated by frameworks like Flask and Django. Jinja has many useful and convenient features and one of them is macros. Macros in Jinja are analogous to functions in other programming languages, thus they help in avoiding code redundancy and have clean and manageable codebase inside jinja templates. The syntax to define the arguments and calling the macros is very similar to Python programming language. We have access to these arguments inside the body of macro and we can utilize them in creating the resultant text. The result of executing a macro is always some text. We can call these macros inside the template inside “{{ <some expression> }}” delimiter.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads