Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return a dict object from Jinja2 macros

Tags:

python

jinja2

I have a separate file for helper macros, so I import one when needed. Here is problematic macro:

{% macro row_cycler(tiles) -%}
    {%- set row1 = [] -%}
    {%- set row2 = [] -%}
    {%- set row3 = [] -%}
    {%- set row4 = [] -%}
    {%- set rows = cycler(row1, row2, row3, row4) -%}
    {% for column in tiles|batch(4) -%}
        {% for tile in column -%}
            {%- do rows.next().append(tile) -%}
        {%- endfor %}
    {%- endfor %}
    {{ dict(row1=row1, row2=row2, row3=row3, row4=row4) }}
{%- endmacro %}

Seems it returns dict, but it's not. It returns "markupsafe.Markup object", it leads to something that:

UndefinedError: 'markupsafe.Markup object' has no attribute 'itervalues'

and so on. How can I force Jinja to return dict without converting?

like image 785
Als Avatar asked Feb 06 '14 19:02

Als


2 Answers

No, macros can only return template snippets (in the form of Markup objects), not Python objects like dictionaries. Use Python code for that instead; add a function to the items passed into the template or add a template global.

In your case it looks as if you are re-implementing the slice() filter, so perhaps that's not even needed in this case.

like image 51
Martijn Pieters Avatar answered Oct 18 '22 04:10

Martijn Pieters


I overcame a similar problem in Ansible (it has a built-in filter from_json) by returning a json string and parsing it back into a dictionary:

{% macro get_dict() -%}
  {%- set d = dict() -%}
  {{- d.update(foo="bar") -}}
  {{- d.update(spam="eggs") -}}
  {{- d|to_json -}}
{%- endmacro %}

{% set d = get_dict()|from_json %}
{% for key, value in d.items() %}
  {{- key }}: {{ value }}
{% endfor %}

If not using Ansible, one could easily define the from_json filter, something like below (where env is an instance of jinja2.Environment):

def from_json(val):
    return json.loads(val)

env.filters["from_json"] = from_json
like image 20
anemyte Avatar answered Oct 18 '22 04:10

anemyte