Elias Probst
Elias Probst

Reputation: 277

Jinja2 - copy variable instead of referencing it

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:

But none of those worked. Is there any way to copy values in Jinja2?

Upvotes: 4

Views: 2867

Answers (2)

gusmb
gusmb

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

Unapiedra
Unapiedra

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

Related Questions