Trouble with python dictionaries and iterating through them with Jinja - python

I have a Python dictionary that looks like this. {0: {'record': u'running fast', 'moreInfo': u'test', 'year': u'2017', 'name': u'Jose la computadora', 'activity': u'Cross Country'}, 1: {'record': u'test', 'moreInfo': u'ttt', 'year': u'2000', 'name': u'Lewdog', 'activity': u'Cross Country'}}
I'm passing it to a Jinja template with Flask. The dictionary is set to the variable databaseQuery and passed to Jinja.
My jinja code looks like this, but nothing shows up on the page.
If I print databaseQuery on the page, I get the whole dictionary, and if I print test, I just get 0 1.
I'm trying to figure out how to iterate through my dictionary and show each value for name on the page.
{% for test in databaseQuery %}
{{test["name"]}}
{% endfor %}
I've looked at this list of dictionary in jinja template but didn't have any luck.
Thanks!

Well you're just iterating through the keys of databaseQuery.
Jinja suppresses some errors so that's why it's not exploding for you.
This isn't a Jinja issue but a python issue; if you iterate through a dictionary without specifying keys, values or items, it'll just loop through the keys, which for you are 0 and 1 which are just integers.
If you want to access just the values, you could do
{% for val in databaseQuery.values() %}
{{ val['name'] }}
{% endfor %}
should get you what you want. It's worth noting unless those integers (0 and 1) will be used for something meaningful, you could just pass up the list of dictionaries and loop through that as you did and that would work.

Iterating a dict produces only the keys. You can do:
{% for k in databaseQuery %}
{{ databaseQuery[k]['name'] }}
{% endfor %}
Or:
{% for k, v in databaseQuery.items() %}
{{ v['name'] }}
{% endfor %}

Hei ;
With python iterating over a dict gives you the key.
a = {1:'test'}
for k in a
will give you 1
Try a[key] to access the values
Edit :
{% for test in databaseQuery %}
{{databaseQuery[test]}}
{% endfor %}

Related

Looping through nested dictionary in Django template

My context dictionary for my Django template is something like the following:
{'key1':'1',
'key2':'2',
'key3':'3',
'key4':{'key5':{'key6':'6', 'key7':'7', 'key8':'8'}}}
I would like to iterate through the dictionary and print something like:
some label = 6
some label = 7
some label = 8
How can I achieve this in my Django template?
What's wrong with this ?
<ul>
{% for key, value in key4.key5.items %}
<li>{{ key }} : {{ value }}</li>
{% endfor %}
</ul>
NB: you didn't ask for looping over all keys in the context, just about accessing key4['key5'] content. if this wasn't wath you were asking for pleasit eadit your question to make it clearer ;-)
I am guessing you want to use a for loop in the django template to do this you must first pass the dictionary to the template in the views file like so make sure you add square brackets around the dictionary like this:
data = [{'key1':'1',
'key2':'2',
'key3':'3',
'key4':{'key5':{'key6':'6', 'key7':'7', 'key8':'8'}}
}]
return render(request,'name of template',{'data':data})
then in the html template:
{% for i in data%}
<p>{{i.key1}}</p>
<p>{{i.key2}}</p>
<p>{{i.key3}}</p>
<p>{{i.key4.key5.key6}}</p>
{% endfor %}
Now when you do the for loop you can access all the iteams in key4 like i have above when I put {{i.key4.key5.key6}}
Here is the docs for the for loop in django templates https://docs.djangoproject.com/en/3.0/ref/templates/builtins/
I am assuming thats what you want to do.
This has worked for me:
{% for key, value in context.items %}
{% ifequal key "key4" %}
{% for k, v in value.items %}
some label = {{ v.key6 }}
some label = {{ v.key7 }}
some label = {{ v.key8 }}
{% endfor %}
{% endif %}
{% endfor %}
If you want to print only what you have mentioned in question then it is possible but if we don't know the exact structure of dictionary then it is possible in django views not in django template.
You can't print value which is also a dictionary one by one in django template,
But you can do this in django view.
Check this post click here and do some changes in views.

I am looking for a quick way to retrieve values from a dictionary in templates

I have the following situation:
{% if accounts.count > 0 %}
{% for account in accounts %}
<div>Balance:<b>{{ my_dict.account.id }}</b></div>
<div><button>Edit</button></div>
{% endfor %}
{% else %}
<p>...</p>
{% endif %}
.
Such arrangement is ok
my_dict.account
But I'll do something like that. I have two dots
my_dict.account.id
Is there any way to do this? It would be a good idea to create a variable in template but it does not work for me
Would be nice to see your my_dict dictionary structure: what is key (is it account id?)
It can be something like this:
my_dict[account.id]
Though if my_dict somehow doesn't have the key, you'll encounter an error. So you might wanna do this instead:
my_dict.get(account.id, 'default value')
'default value' is what will be returned in case if there's no such key in my_dict.

Display of dictionary in django

My List
book_details = [
{'author':'abc', 'book_name':'xyz', 's_no':1},
{'author':'efg', 'book_name':'ijk', 's_no':2}
]
My code:
{% for dict in details %}
<tr>
{% for key, value in dict.items %}
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}
Output :
Author Book_name S_no
Desired output:
S_no Book_name Author
I'm new to django , please guide.
Right now you are iterating through each key-value pair in the dictionary, so your code is outputting dictionary values in the order in which they are stored in the dictionary, which happens to be:
Author Book_name S_no
So, you have two options.
Change the order in which these attributes are stored in the dictionary. If you change the structure of your dictionaries from {'author': 'abc', 'book_name':'xyz','s_no':1} to {'s_no':1, 'book_name':'xyz', 'author': 'abc'}, iterating over the key-value pairs will return these attributes in the desired order. However, this is not a very flexible solution, so I would suggest the second option.
Change the way you output dictionary values. Instead of iterating through all the key-value pairs in whatever order they happen to be in, you can explicitly define the order in which you want to output dictionary values by changing this:
{% for key,value in dict.items %}
<td>{{value}}</td>
{% endfor %}
to this:
{% for key in ['S_no', 'Book_name', 'Author'] %}
<td>{{dict[key]}}</td>
{% end for %}
This solution has the added benefit of being quite easy to modify if, later on, you decide you want to output these values in another order.
{% for dict in details %}
<tr>
<td>{{dict.s_no}}</td>
<td>{{dict.book_name}}</td>
<td>{{dict.author}}</td>
</tr>
{% endfor%}

How to get values from dictionary in jinja when key is a variable?

I'm trying to retrieve entries from a python dictionary in jinja2, but the problem is I don't know what key I want to access ahead of time - the key is stored in a variable called s.course. So my problem is I need to double-substitute this variable. I don't want to use a for loop because that will go through the dictionary way more than is necessary. Here's a workaround that I created, but it's possible that the s.course values could change so obviously hard-coding them like this is bad. I want it to work essentially like this:
{% if s.course == "p11" %}
{{course_codes.p11}}
{% elif s.course == "m12a" %}
{{course_codes.m12a}}
{% elif s.course == "m12b" %}
{{course_codes.m12b}}
{% endif %}
But I want it to look like this:
{{course_codes.{{s.course}}}}
Thanks!
You can use course_codes.get(s.course):
>>> import jinja2
>>> env = jinja2.Environment()
>>> t = env.from_string('{{ codes.get(mycode) }}')
>>> t.generate(codes={'a': '123'}, mycode='a').next()
u'123'
There is no need to use the dot notation at all, you can do:
"{{course_codes[s.course]}}"
I'm using Jinja with Salt, and I've found that something like the following works well:
{% for role in pillar.packages %}
{% for package in pillar['packages'][role] %}
install_{{ package }}:
pkg.installed:
- name: {{ package }}
{% endfor %}
{% endfor %}
That is, use the more verbose [ ] syntax and leave the quotes out when you need to use a variable.

How to use django template dot notation inside a for loop

I am trying to retrieve the value of a dictionary key and display that on the page in a Django template:
{% for dictkey in keys %}
<p> {{ mydict.dictkey }} </p>
{% endfor %}
(let's say 'keys' and 'mydict' have been passed into the template in the Context)
Django renders the page but without the dictionary contents ("Invalid template variable")
I assume the problem is that it is trying to do mydict['dictkey'] instead of mydict[actual key IN the variable dictkey]? How does one "escape" this behavior?
Thanks!
UPDATE:
Based on the answers received, I need to add that I'm actually looking specifically for how to achieve a key lookup inside a for loop. This is more representative of my actual code:
{% for key, value in mydict1.items %}
<p> {{ mydict2.key }} </p>
{% endfor %}
Basically, I have two dictionaries that share the same keys, so I can't do the items() trick for the second one.
See this answer to a (possibly duplicate) related question.
It creates a custom filter that, when applied to a dictionary with a key as it's argument, does the lookup on the dictionary using the key and returns the result.
Code:
#register.filter
def lookup(d, key):
if key not in d:
return None
return d[key]
Usage:
{% for dictkey in dict1.keys %}
<p> {{ dict2|lookup:dictkey }} </p>
{% endfor %}
Registering the filter is covered in the documentation.
I find it sad that this sort of thing isn't built in.
From http://docs.djangoproject.com/en/dev/ref/templates/builtins/#for
This can also be useful if you need to access the items in a dictionary. For example, if your context contained a dictionary data, the following would display the keys and values of the dictionary:
{% for key, value in data.items %}
{{ key }}: {{ value }}
{% endfor %}
The trick is that you need to call dict.items() to get the (key, value) pair.
See the docs: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#for
{% for key, value in data.items %}
{{ key }}: {{ value }}
{% endfor %}

Categories

Resources