jinja2:宏选宏或动态宏调用

blu*_*ank 7 python templates jinja2

我有一个我正在经历的命名元组列表,每个渲染要求略有不同,所以我想根据属性调用适当的宏.我有的是这个:

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

但我想要的是:

...iterating through list of items
{{ call macro based off item.type_of }}
Run Code Online (Sandbox Code Playgroud)

在常规python的这一点上,我会做类似的事情

getattr(object_with_method_to_produce_templates, item)
Run Code Online (Sandbox Code Playgroud)

但是还没有找到一种有效使用attr过滤器的方法(如果我可以在这种情况下正确使用它).

我发现flask.get_template_attribute在其他地方寻找可能很有意思(如果我可以提前完成所有操作并将预先计算好的预先格式化的项目发送到模板).可能太多,超出了我此时想做的事情.

什么是从各种宏列表中调用的更好的方法,而不是将来可能会变得相当大的if列表?似乎是一个常见的问题,但我没有偶然发现我正在寻找的确切答案.

编辑:

我将此添加到我正在做的事情,尝试生成一个可调用的宏作为我想要渲染的项目的一部分

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

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

 template = get_template_attribute(test_template, 'test_macro')
Run Code Online (Sandbox Code Playgroud)

...在模板中...然后为每个项目迭代项目

{{ item.template("testing this method") }}
Run Code Online (Sandbox Code Playgroud)

哪种工作,但只生成字母的字母,而不是常规的宏(即div不会呈现为div,只作为文本).

<div id="test-div">sent to me: testing this method</div>
Run Code Online (Sandbox Code Playgroud)

所以我需要给模板一些上下文,或者这更接近目标,但似乎不对.

EDIT2:

{{ item.template("testing this method")|safe }}
Run Code Online (Sandbox Code Playgroud)

返回我正在寻找的东西,所以这是可以接受的,我可能能够绕过我所拥有的namedtuple安排,只是传递一个宏...我想更多的工作.这是最佳/可取的还是一团糟?

Mat*_*rty 5

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

@contextfilter
def call_macro_by_name(context, macro_name, *args, **kwargs):
    return context.vars[macro_name](*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

请在此处查看完整的答案.