28

I am not able to append add a new entry into a dictionary object while using jinja2 template.

For example, here I am using jinja2 template and I have created a data variable which is a dictionary. And after checking some if condition I WANT to append location attribute to the data object e.g.

{%- set data = {
                  'name' : node.Name,
                  'id' : node.id,
               }
-%}

{% if node.location !="" %}
    data.append({'location': node.location}) 
{% endif %}

However I could not find a way to achieve this and am getting the UndefinedError:

jinja2.exceptions.UndefinedError: 'dict object' has no attribute 'append'

Has anyone faced this issue or could provide a reference to solve this?

I searched the web but could not find a solution i.e. how to achieve adding an entry to the dict object in the Jinja.

I have referred following and other web resources:

  1. http://cewing.github.io/training.codefellows/assignments/day22/jinja2_walkthrough.html
  2. In Jinja2 whats the easiest way to set all the keys to be the values of a dictionary?
  3. https://github.com/saltstack/salt/issues/27494
Community
  • 1
  • 1
hemant_maverik
  • 399
  • 1
  • 4
  • 8
  • Please choose one of the answers that helped and accept it with the checkmark, so other uses can see, which answer solved the problem. – allo Mar 24 '17 at 22:18

4 Answers4

24

Without the jinja2.ext.do extension, you can do this:

{% set x=my_dict.__setitem__("key", "value") %}

Disregard the x variable and use the dictionary which is now updated.

UPD: Also, this works for len() (__len__()), str() (__str__()), repr() (__repr__()) and many similar things.

  • hmm, does not work, with ```myString="{% set data={} %}{% set data2=data.__setitem__('key','value') %}{{ data2['key'] }}"; a=Environment(loader=BaseLoader()).from_string(myString); a.render()``` the output is `''` – K. Frank Feb 10 '19 at 00:53
  • @K.Frank, the answer says to disregard the variable that you assign to. `{% set data={} %}{% set x=data.__setitem__('key', 'value') %}{{ data['key'] }}` – sleblanc May 27 '19 at 22:05
  • 3
    I get `access to attribute '__setitem__' of 'dict' object is unsafe` when trying this (Python3, running [dbt](https://www.getdbt.com/)=0.14.2) – dsz Oct 03 '19 at 23:42
13

Dictionaries do not have the append method. You can add a key-value pair like this though:

{% do data['location']=node.location %} 

or

{% do data.update({'location': node.location}) %}
slm
  • 14,096
  • 12
  • 98
  • 116
alpert
  • 4,264
  • 1
  • 16
  • 25
  • 1
    Thanks Alpert! Though after using {% do data['location']=node.location %} or {% do data.update({'location': node.location}) %} I still got the TemplateSyntaxError, but after some searching on web I discovered my jinja environment was missing the jinja2.ext.do extention because of which that "do" tag was throwing the syntax error. Now it is working fine :) Thanks again!! – hemant_maverik Apr 28 '16 at 06:27
  • This link helped as well : http://stackoverflow.com/questions/2703013/how-can-i-modify-merge-jinja2-dictionaries – hemant_maverik Apr 28 '16 at 06:40
  • 5
    The first `{% do data['location'] = node.location %}` does not work for me, perhaps because `data['location'] = node.location` is not actually an expression and does not work with `do`, which expects expressions? – Kye W Shi Jan 02 '18 at 20:17
9

Key takeaways:

  1. dictionary does not support append().
  2. You can add the new item to the data dictionary by using {% do ... %} tag as shown here:

    {% do data.update({'location': node.location}) %}
    
  3. However, for the "do" tag to work properly you need to add the jinja2.ext.do extension to your jinja Environment.

slm
  • 14,096
  • 12
  • 98
  • 116
hemant_maverik
  • 399
  • 1
  • 4
  • 8
8

Without the do extension:

{%- set _ = dict.update({c.name: c}) -%}

Works in base Jinja2 on Python 3, where the __setitem__ solutions give me:

access to attribute '__setitem__' of 'dict' object is unsafe
dsz
  • 3,927
  • 33
  • 31
  • FYI - this works well for updating saltstack pillars with jinja 2 prior to state execution with python 3 clients. – Peter M Jan 10 '20 at 20:56