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.