如何递归合并Jinja2中的dicts而无需定义自定义过滤器?
所以
{ a: { b: 'ab', d: 'ad' } }
+ { a: { b: 'aX', e: 'ae' } }
变为
{ a: { b: 'aX', d: 'ad', e: 'ae' } }
我正在将一些Mako模板迁移到Jinja2。使用Mako我可以简单地使用一个小的python代码片段为我做这个......我不能使用自定义过滤器的原因是,我根本无法在模板引擎中注册自定义过滤器,因为我无法直接访问它。
答案 0 :(得分:2)
我终于找到了解决问题的方法:
{%- macro deep_merge(a, b): %}
{%- for k,v in b.items(): %}
{%- if v is not defined: %}
{%- do a.pop(k) %}
{%- else: %}
{%- if v is mapping: %}
{%- if a[k] is not mapping: %}
{%- do a.update({ k: { } }) %}
{%- endif %}
{%- do deep_merge(a[k], v) %}
{%- else: %}
{%- do a.update({ k: v }) %}
{%- endif %}
{% endif %}
{%- endfor %}
{%- endmacro %}
{%- do deep_merge(a, b) %}
这段Jinja2-Code递归地将b
合并到a
中,覆盖重复键(b
优先)并从a
中删除设置为{{}的键1}} null
。
答案 1 :(得分:1)
这很难看,但听起来你的情况有点Abby Normal:
{# Untested code - may not work #}
{% macro merge(destination) %}
{% for provider in varargs %}
{% for key, value in provider.items() %}
{% if value is mapping %}
{% set intermediate = {} %}
{% do merge(intermediate, destination.get(key, {}), value) %}
{% do destination[key] = intermediate %}
{% else %}
{% do destination[key] = value %}
{% endif %}
{% endfor %}
{% endfor %}
{% endmacro %}
你可以像这样使用它:
{% set result = {} %}
{% do merge(result, first_values, second_values) %}
{# result is now the merger of first_values and second_values #}