*args, **kwargs in jinja2 macros
Question:
How are extra args & kwargs handled for a Jinja2 macro? The documentation isn’t exactly clear offhand.
For example, this is clearly wrong:
{% macro example_1(one, two, **kwargs) %}
do macro stuff
{% endmacro %}
which results in
jinja2.exceptions.TemplateSyntaxError
TemplateSyntaxError: expected token 'name', got '**'
The documentation says:
kwargs
Like varargs but for keyword arguments. All unconsumed keyword arguments are stored in this special variable.
Unfortunately, any combo of extra keyword arguments is an error,
{% macro example_2(one, two) %}
do macro stuff
{% endmacro %}
{{ example_2(one, two, test='test') }}
TypeError: macro 'example_2' takes no keyword keyword argument 'test'
I have no examples and am not poking about in the Jinja2 source code atm. The documentation isn’t clear to me at this point. Any thoughts appreciated.
Answers:
The trick is that kwargs
has to be accessed at least once in any macro that should accept them. That is to say, you must call {{ kwargs }}
once in macro body without declaring it in macro argument list. The same is true for {{ varargs }}
.
This will not work
{% macro example_2(one, two) %}
* {{one}} - {{two}}
{% endmacro %}
{{example_2(1, 2, test="Hello")}}
This will
{% macro example_2(one, two) %}
* {{one}} - {{two}}
* {{kwargs}}
{% endmacro %}
{{example_2(1, 2, test="Hello")}}
Just to add to Sean Viera’s answer, the kwargs
object will be a dictionary so if you want to use it you can iterate over it by accessing the items()
method, like in normal Python:
{% macro iterate_kwargs() %}
{% for key, value in kwargs.items() %}
The key, {{ key }}, has a value of {{ value }}
{%- endfor -%}
{% endmacro %}
{{ iterate_kwargs(id=123, colour="blue", size="S") }}
This will output the following:
The key, id, has a value of 123
The key, colour, has a value of blue
The key, size, has a value of S
This was written and tested using dbt so may not be available to all tools that use Jinja
How are extra args & kwargs handled for a Jinja2 macro? The documentation isn’t exactly clear offhand.
For example, this is clearly wrong:
{% macro example_1(one, two, **kwargs) %}
do macro stuff
{% endmacro %}
which results in
jinja2.exceptions.TemplateSyntaxError
TemplateSyntaxError: expected token 'name', got '**'
The documentation says:
kwargs
Like varargs but for keyword arguments. All unconsumed keyword arguments are stored in this special variable.
Unfortunately, any combo of extra keyword arguments is an error,
{% macro example_2(one, two) %}
do macro stuff
{% endmacro %}
{{ example_2(one, two, test='test') }}
TypeError: macro 'example_2' takes no keyword keyword argument 'test'
I have no examples and am not poking about in the Jinja2 source code atm. The documentation isn’t clear to me at this point. Any thoughts appreciated.
The trick is that kwargs
has to be accessed at least once in any macro that should accept them. That is to say, you must call {{ kwargs }}
once in macro body without declaring it in macro argument list. The same is true for {{ varargs }}
.
This will not work
{% macro example_2(one, two) %}
* {{one}} - {{two}}
{% endmacro %}
{{example_2(1, 2, test="Hello")}}
This will
{% macro example_2(one, two) %}
* {{one}} - {{two}}
* {{kwargs}}
{% endmacro %}
{{example_2(1, 2, test="Hello")}}
Just to add to Sean Viera’s answer, the kwargs
object will be a dictionary so if you want to use it you can iterate over it by accessing the items()
method, like in normal Python:
{% macro iterate_kwargs() %}
{% for key, value in kwargs.items() %}
The key, {{ key }}, has a value of {{ value }}
{%- endfor -%}
{% endmacro %}
{{ iterate_kwargs(id=123, colour="blue", size="S") }}
This will output the following:
The key, id, has a value of 123
The key, colour, has a value of blue
The key, size, has a value of S
This was written and tested using dbt so may not be available to all tools that use Jinja