Using **kwargs in Flask/Jinja

On my record collecting website, Recordbin, I am using a macro to build tables of user’s record collections. The macro has a few specific arguments that are required, but depending on the situation I might need to pass it other variables. I need some of the tables to have a specific class and other tables to have no class at all. Because Jinja macros are similar to Python functions, I figured using **kwargs would be a good option. However, Jinja handles kwargs a little differently than regular Python.

Googling “Jinja kwargs” yields scattered Stack Overflow questions, so I would like to write out an example. At the very least it will help with my own understanding :)

The main difference is Jinja does not require the keyword **kwargs to be passed to the macro as an argument. In fact, doing so will cause an error. For example, this macro:

{% macro render_div(**kwargs) %}
<div class="{{ class }}" >
<p>Lorem ipsum.</p>
</div>
{% endmacro %}

returns…

TemplateSyntaxError: expected token 'name', got '**'

Additionally, if I remove the keyword **kwargs from the macro arguments, I get:

TypeError: macro 'render_div' takes no keyword argument 'class'

In order to use key word arguments as part of my macro. I have to access them as part of the kwargs dict. It works just like any other dictionary. Notice that it is just “kwargs” and not “**kwargs”.

{% macro render_div() %}
<div class="{{ kwargs['class'] }}">
<p>Lorem ipsum</p>
</div>
{% endmacro %}

In the template:

{% from 'macro/render_div.html' import render_div %}
{{ render_div(class="yolo") }}
{{ render_div() }}

Will yield…

<div class="yolo">
<p>Lorem ipsum</p>
</div>
<div class="">
<p>Lorem ipsum</p>
</div>

To summarize, to use keyword arguments or kwargs as part of a Jinja macro, you call them in the macro output and not in the macro arguments.