【问题标题】:How can I indirectly call a macro in a Jinja2 template?如何在 Jinja2 模板中间接调用宏?
【发布时间】:2012-05-17 04:30:32
【问题描述】:

我正在尝试做这样的事情:

{% macro obj_type_1 %}
stuff
{% endmacro %}
{% macro obj_type_2 %}
stuff
{% endmacro %}

{{ (obj|get_type)(obj) }}

在这个例子中,get_type 是一个过滤器,它会返回obj_type_1obj_type_2——即调用obj 的宏的名称。我不想用配置输出标记obj,因为现在obj 在多个模板中用作结构数据,根据上下文使用不同的标记呈现。

我知道这里的语法有点受折磨,但我认为这是因为我想做的事情在 Jinja 模板中无法立即实现。我正在尝试用模板替换一些配置生成代码中的 if/elif/else 废话,但这似乎是一个症结所在。

【问题讨论】:

  • 所以你基本上是在寻找一种在 Jinja2 中eval() 的方法?
  • 接近;我想按名称调用宏。

标签: python jinja2


【解决方案1】:

可以通过 import dict 用法简单地调用宏:

ma​​cros.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】:

    您可以创建一个 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)
    

    【讨论】:

      【解决方案3】:

      个人而言,由于 get_type 用作调度程序,因此将其实现为 jinja 宏会更透明,该宏会根据 obj 的类型调用专门的宏。这消除了它返回可调用宏的需要,同时整合了专用宏和指示如何/何时使用它们的逻辑。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-01
        • 2012-07-04
        • 2020-12-10
        • 1970-01-01
        • 2013-03-25
        • 2011-09-17
        • 1970-01-01
        相关资源
        最近更新 更多