从 Jinja2 宏返回一个 dict 对象

Als*_*Als 5 python jinja2

我有一个单独的帮助宏文件,所以我在需要时导入一个。这是有问题的宏:

{% 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 %}
Run Code Online (Sandbox Code Playgroud)

似乎它返回 dict,但事实并非如此。它返回“markupsafe.Markup 对象”,它导致:

UndefinedError: 'markupsafe.Markup object' has no attribute 'itervalues'
Run Code Online (Sandbox Code Playgroud)

等等。如何强制 Jinja 在不转换的情况下返回 dict?

ane*_*yte 7

我通过返回一个字符串并将其解析回字典来克服了 Ansible 中的类似问题(它有一个内置的过滤器from_json) :json

{% 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 %}
Run Code Online (Sandbox Code Playgroud)

如果不使用 Ansible,可以轻松定义from_json过滤器,如下所示(其中env是 的实例jinja2.Environment):

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

env.filters["from_json"] = from_json
Run Code Online (Sandbox Code Playgroud)


Mar*_*ers 5

不,宏只能返回模板片段(以Markup对象的形式),而不是像字典这样的 Python 对象。改为使用 Python 代码;向传递给模板的项目添加函数或添加模板全局。

在您的情况下,您似乎正在重新实现slice()filter,因此在这种情况下甚至不需要这样做。