我们说我有这个带宏的模板(这些是简化的):
{# macros.html #}
{% macro a(opts = {}) %}
{{ opts.a }}
{% endmacro %}
{% macro b(opts = {}) %}
{{ opts.b }}
{% endmacro %}
和包含覆盖
的这个{# macros_override.html #}
{% macro a(opts = {}) %}
Overridden: {{ opts.a }}
{% endmacro %}
然后我希望在同一名称空间macros
{# template.html #}
{% import 'macros.html' as macros %}
{% import 'macros_override.html' as macros %}
{{ macros.a({ 'a': 'foo' }) }}
{{ macros.b({ 'b': 'bar' }) }}
和我期望的输出:
Overridden: foo
bar
但b
未定义。我尝试将macros_override.html
模板更改为:
{# macros_override.html #}
{% extends 'macros.html' %}
{% macro a(opts = {}) %}
Overridden: {{ opts.a }}
{% endmacro %}
然后仅将重叠模板导入为宏,但在这种情况下宏a
未被覆盖,我不知道原因。
我可以通过其他导入以某种方式覆盖jinja中的导入宏吗?
答案 0 :(得分:6)
所以在我的同事的帮助下,我明白了。
在孩子之后评估父模板 http://jinja.pocoo.org/docs/dev/faq/#my-macros-are-overridden-by-something
这意味着如果你想使用第二个选项,你只需要在父模板中检查宏是否存在。
像这样工作:
{# macros.html #}
{% if not a %}
{% macro a(opts = {}) %}
{{ opts.a }}
{% endmacro %}
{% endif %}
{% if not b %}
{% macro b(opts = {}) %}
{{ opts.b }}
{% endmacro %}
{% endif %}
和包含覆盖
的这个{# macros_override.html #}
{% extends 'macros.html' %}
{% if not a %}{# I repeat here in case there's gonna be a double extend #}
{% macro a(opts = {}) %}
Overridden: {{ opts.a }}
{% endmacro %}
{% endif %}
然后就像这样导入它们
{# template.html #}
{% import 'macros_override.html' as macros %}
{{ macros.a({ 'a': 'foo' }) }}
{{ macros.b({ 'b': 'bar' }) }}
并按预期输出
Overridden: foo
bar
答案 1 :(得分:0)
我们遇到了类似的问题,我们希望用户能够通过扩展默认模板来覆盖单个宏。重复 {% if not a %}
在这里有点乏味,所以我们用 Jinja2 扩展修复了这个问题:
class DefaultMacroExtension(ext.Extension):
"""
This extension provides a new `{% defaultmacro %}` statement, which defines a macro only if it does not exist.
For example,
{% defaultmacro example() %}
test 123
{% enddefaultmacro %}
is equivalent to
{% macro default_example() %}
test 123
{% endmacro %}
{% if not example %}
{% macro example() %}
test 123
{% endmacro %}
{% endif %}
The default implementation is also available as `default_$macroname`, which makes it possible
to reference it in the override.
"""
tags = {"defaultmacro"}
def parse(self, parser):
m = nodes.Macro(lineno=next(parser.stream).lineno)
name = parser.parse_assign_target(name_only=True).name
m.name = f"default_{name}"
parser.parse_signature(m)
m.body = parser.parse_statements(("name:enddefaultmacro",), drop_needle=True)
if_stmt = nodes.If(
nodes.Not(nodes.Name(name, "load")),
[nodes.Macro(name, m.args, m.defaults, m.body)],
[],
[],
)
return [m, if_stmt]
env = Environment(
extensions=[DefaultMacroExtension],
)