重新定义导入的jinja宏

vxs*_*xsx 5 jinja2

假设我有这个带有宏的模板(这些是简化的):

{# macros.html #}
{% macro a(opts = {}) %}
   {{ opts.a }}
{% endmacro %}

{% macro b(opts = {}) %}
   {{ opts.b }}
{% endmacro %}
Run Code Online (Sandbox Code Playgroud)

而这一个包含覆盖

{# macros_override.html #}
{% macro a(opts = {}) %}
    Overridden: {{ opts.a }}
{% endmacro %}
Run Code Online (Sandbox Code Playgroud)

然后我希望在同一名称空间下有一个包含所有这些宏的模板 macros

{# template.html #}
{% import 'macros.html' as macros %}
{% import 'macros_override.html' as macros %}

{{ macros.a({ 'a': 'foo' }) }}
{{ macros.b({ 'b': 'bar' }) }}
Run Code Online (Sandbox Code Playgroud)

和我期望的输出:

Overridden: foo
bar
Run Code Online (Sandbox Code Playgroud)

但是b未定义.我试图将macros_override.html模板更改为:

{# macros_override.html #}
{% extends 'macros.html' %}
{% macro a(opts = {}) %}
    Overridden: {{ opts.a }}
{% endmacro %}
Run Code Online (Sandbox Code Playgroud)

然后只导入覆盖模板作为宏,但a在这种情况下不会覆盖宏,我真的不知道为什么.

我可以通过其他导入以某种方式覆盖jinja中的导入宏吗?

vxs*_*xsx 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 %}
Run Code Online (Sandbox Code Playgroud)

而这一个包含覆盖

{# 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 %}
Run Code Online (Sandbox Code Playgroud)

并且就像这样导入它们

{# template.html #}
{% import 'macros_override.html' as macros %}

{{ macros.a({ 'a': 'foo' }) }}
{{ macros.b({ 'b': 'bar' }) }}
Run Code Online (Sandbox Code Playgroud)

它按预期输出

Overridden: foo
bar
Run Code Online (Sandbox Code Playgroud)