0

我正在通过 jingo 使用 jinja2 开发 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在示例中),当涉及的逻辑太复杂时,这是不可行的。

4

2 回答 2

1

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

@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)
于 2012-12-06T07:21:41.883 回答
0

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

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

env.globals['render_link'](obj)

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

于 2012-12-05T23:52:21.917 回答