jinja2模板语言:宏选择宏或动态宏调用

7
我有一个命名元组的列表,我正在遍历每个命名元组,它们在呈现要求上略有不同,因此我想根据属性调用适当的宏。 我手头的代码如下:
{% macro format_item(item) %}
    {% if item.type_of == 'a' %}
        {{ format_a(item) }}
    {% elif item.type_of == 'b' %}
        {{ format_b(item) }}
    {% elif item.type_of == 'c'%}
        {{ format_c(item) }}
    {% elif item.type_of == 'd'%}
        {{ format_d(item) }}
    {% else %}
        {{ format_general(item) }}
    {% endif %}
{% endmacro %}

但是我想要的是类似这样的东西:
...iterating through list of items
{{ call macro based off item.type_of }}

在普通的Python中,此时我会做类似于以下的操作:

getattr(object_with_method_to_produce_templates, item)

但是我还没有想出如何有效地使用attr过滤器(如果我在这种情况下能够正确使用它的话)。

我在其他地方发现了flask.get_template_attribute,这可能很有趣(如果我可以提前计算和格式化所有内容并将其发送到模板中)。也许这太复杂了,超出了我此时想要做的事情。

有什么更好的方法可以从各种宏列表中调用,而不是一个if-then列表(未来可能会变得非常庞大)?看起来这是一个常见的问题,但我没有找到我正在寻找的确切答案。

编辑:

我尝试生成可调用的宏作为我想要呈现的项目的一部分

from flask import get_template_attribute
from jinja2 import Template
test_template = Template('{% macro test_macro(item) %}<div id="test-div">sent to me: {{ item }}</div>{% endmacro %}')

...在项目生成中...

 template = get_template_attribute(test_template, 'test_macro')

...在模板中...迭代项目,然后对于每个项目

{{ item.template("testing this method") }}

这种方法有点用,但只能逐字生成字符串,不能像普通宏一样生成(例如,div不会被呈现为div,只是作为文本处理)。

<div id="test-div">sent to me: testing this method</div>

我需要给模板一些上下文或者类似的东西,这样才更符合我的意图,但是感觉不太对。

编辑2:

{{ item.template("testing this method")|safe }}

返回了我所需要的内容,所以这是可以接受的,我可能可以绕过之前使用的namedtuple安排,只需传递一个带有宏的...更多工作,我想。但这是最优/可取的还是一团糟呢?


请查看Jinja文档中的HTML转义和safe过滤器。 - voscausa
好的,我已经查看了它们,但还没有做出我需要的确切连接。我认为我所做的是创建一个宏作为代码块,但没有将其标记为HTML(文件扩展名会指示),因此该宏只会呈现为纯文本,嗯,让我们在其中探索一下。 - blueblank
1个回答

6

您可以创建一个Jinja2过滤器,从当前上下文中获取宏,然后评估该宏。该过滤器如下:

@contextfilter
def call_macro_by_name(context, macro_name, *args, **kwargs):
    return context.vars[macro_name](*args, **kwargs)

请看完整答案这里

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接