使用 jinja2 宏从过滤器使用金戈



我正在开发一个使用jinja2通过jingo的Django应用程序。我有一个在templates/macros.html中定义的宏,我需要从helpers.py中定义的过滤器调用它,因为我必须传递它的参数中涉及某种 python 逻辑。有什么办法吗?

我想要实现的是这样的目标:

templates/macros.html

{% macro render_link(obj) -}
    <a href="{{ obj.get_absolute_url() }}">{{ obj }}</a>
-%}

helpers.py

@register.filter
def as_link(obj_or_list):
    if hasattr(obj_or_list, '__iter__'):
        for obj in obj_or_list:
            # call `render_link(obj)` here and concat results somehow
    else:
        # call `render_link(obj_or_list)` here 

每当我需要它时,在我的模板中:

{{ an_object|as_link }}

我需要在这里使用过滤器,因为我需要在将参数传递给宏之前对参数做一些事情。我知道我可以在宏本身中编写逻辑,但我需要在 jinja2 环境中添加一些方法(例如示例中的 hasattr),当所涉及的逻辑太复杂时,这是不可行的。

经过一番调查,我提出了一个解决方案。宏是在模板中定义的,所以首先我需要加载它。阅读源代码,我发现了如何从模板实例中获取宏函数,因此这是正确的方法:

@register.filter()
def as_link(obj_or_list):
    from jingo import env
    template = env.get_template('macros.html')
    render_link = template.module.render_link
    if hasattr(obj_or_list, '__iter__'):
        return ''.join((render_link(obj) for obj in obj_or_list))
    return render_link(obj_or_list)

我不知道这是否有效,但也许宏已注册为全局函数。宏和全局 Python 函数可以从模板以相同的方式调用。

如果您的宏已注册,您可以:

env.globals['render_link'](obj)

如果这现在有效,则始终可以将宏代码作为 Python 代码包含在筛选器中。在你的过滤器中,你拥有所有的Python功能。

最新更新