我正在尝试做这样的事情:
{% macro obj_type_1 %}
stuff
{% endmacro %}
{% macro obj_type_2 %}
stuff
{% endmacro %}
{{ (obj|get_type)(obj) }}
在此示例中,get_type
是一个过滤器,它会返回obj_type_1
或obj_type_2
- 即要调用obj
的宏的名称。我不想用配置输出标记obj
,因为现在obj
在几个模板中用作结构数据,根据上下文使用不同的标记进行渲染。
我知道这里的语法有点折磨,但我认为这是因为我想要做的事情在Jinja模板中不可能立即实现。我试图用模板替换一些if / elif / else废话的一些配置生成代码,但这一点似乎是一个棘手的问题。
答案 0 :(得分:8)
您可以创建一个Jinja2过滤器,从当前上下文中获取宏,然后评估宏。过滤器是:
@contextfilter
def call_macro_by_name(context, macro_name, *args, **kwargs):
return context.vars[macro_name](*args, **kwargs)
如果您的应用程序需要,您可以在context.vars中查找宏之前对macro_name执行字符串操作。
以下是一个完整的例子:
#!/usr/bin/env python
from jinja2 import Environment, contextfilter
@contextfilter
def call_macro_by_name(context, macro_name, *args, **kwargs):
return context.vars[macro_name](*args, **kwargs)
template_string = """\
{%- macro MyMacro(item) %}MyMacro({{ item }}){% endmacro -%}
{{ MyMacro('direct') }}
{{ 'MyMacro' | macro('indirect') }}
"""
env = Environment()
env.filters['macro'] = call_macro_by_name
template = env.from_string(template_string)
print(template.render())
打印
MyMacro(direct)
MyMacro(indirect)
答案 1 :(得分:2)
可以通过import dict用法简单地调用宏:
<强> macros.html 强>
{% macro render_foo(value) %}
HELLO {{ value }}!
{% endmacro %}
<强> my_view.html 强>
{% import "macros.html" as my_macros %}
{% set macro_name = 'render_' + dynamic_content %}
{{ my_macros[macro_name]('world') }}
渲染为:
HELLO world!
答案 2 :(得分:0)
就个人而言,由于get_type被用作调度程序,因此将其实现为基于obj类型调用专用宏的jinja宏会更加透明。这使得它无需返回可调用的宏,同时整合专用宏和指示如何/何时使用它们的逻辑。