Reputation: 277
I'd like to be able to copy a variable in Jinja2 (2.10
) instead of just referencing it, but couldn't find a way to do it.
See the following example:
from jinja2 import Environment
from jinja2.ext import do
env = Environment(extensions=[do])
template = env.from_string('''
{%- set base = {"elems": {"a": "aa"}} -%}
{%- set data = {"elems": base.elems} -%}
{%- do data.elems.update({"a": "bb"}) -%}
{{ base.elems.a }} - "aa" expected
{{ data.elems.a }} - "bb" expected
''')
template.render()
The result is: 'bb - "aa" expected\nbb - "bb" expected'
So this means that data.elems
is not a copy of base.elems
, but a reference to it instead.
I need to have a copy of base.elems
in data.elems
instead.
I tried:
base.get('elems')
base|attr('elems')
But none of those worked. Is there any way to copy values in Jinja2?
Upvotes: 4
Views: 2867
Reputation: 21
This didn't work for me when I tried to copy the whole dictionary. I ended up getting the copy by doing the following:
{% set newdict = olddict | to_json | from_json %}
Note: in my case I am using Jinja2 with Ansible and not python directly
Upvotes: 2
Reputation: 16197
$ python q54718238.py
aa - "aa" expected
bb - "bb" expected
The trick is knowing that a lot of Python's data types are by reference. So, calling copy()
on the object fixes it. Note that I changed {%- set data = {"elems": base.elems} -%}
to {%- set data = {"elems": base.elems.copy()} -%}
.
from jinja2 import Environment
from jinja2.ext import do
env = Environment(extensions=[do])
template = env.from_string('''
{%- set base = {"elems": {"a": "aa"}} -%}
{%- set data = {"elems": base.elems.copy()} -%}
{%- do data.elems.update({"a": "bb"}) -%}
{{ base.elems.a }} - "aa" expected
{{ data.elems.a }} - "bb" expected
''')
print(template.render())
Upvotes: 6