how to iterate through dictionary in a dictionary in django template? - python

My dictionary looks like this(Dictionary within a dictionary):
{'0': {
'chosen_unit': <Unit: Kg>,
'cost': Decimal('10.0000'),
'unit__name_abbrev': u'G',
'supplier__supplier': u"Steve's Meat Locker",
'price': Decimal('5.00'),
'supplier__address': u'No\r\naddress here',
'chosen_unit_amount': u'2',
'city__name': u'Joburg, Central',
'supplier__phone_number': u'02299944444',
'supplier__website': None,
'supplier__price_list': u'',
'supplier__email': u'ss.sss#ssssss.com',
'unit__name': u'Gram',
'name': u'Rump Bone',
}}
Now I'm just trying to display the information on my template but I'm struggling. My code for the template looks like:
{% if landing_dict.ingredients %}
<hr>
{% for ingredient in landing_dict.ingredients %}
{{ ingredient }}
{% endfor %}
Print {{ landing_dict.recipe_name }}
{% else %}
Please search for an ingredient below
{% endif %}
It just shows me '0' on my template?
I also tried:
{% for ingredient in landing_dict.ingredients %}
{{ ingredient.cost }}
{% endfor %}
This doesn't even display a result.
I thought perhaps I need to iterate one level deeper so tried this:
{% if landing_dict.ingredients %}
<hr>
{% for ingredient in landing_dict.ingredients %}
{% for field in ingredient %}
{{ field }}
{% endfor %}
{% endfor %}
Print {{ landing_dict.recipe_name }}
{% else %}
Please search for an ingredient below
{% endif %}
But this doesn't display anything.
What am I doing wrong?

Lets say your data is -
data = {'a': [ [1, 2] ], 'b': [ [3, 4] ],'c':[ [5,6]] }
You can use the data.items() method to get the dictionary elements. Note, in django templates we do NOT put (). Also some users mentioned values[0] does not work, if that is the case then try values.items.
<table>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
</tr>
{% for key, values in data.items %}
<tr>
<td>{{key}}</td>
{% for v in values[0] %}
<td>{{v}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
Am pretty sure you can extend this logic to your specific dict.
To iterate over dict keys in a sorted order - First we sort in python then iterate & render in django template.
return render_to_response('some_page.html', {'data': sorted(data.items())})
In template file:
{% for key, value in data %}
<tr>
<td> Key: {{ key }} </td>
<td> Value: {{ value }} </td>
</tr>
{% endfor %}

This answer didn't work for me, but I found the answer myself. No one, however, has posted my question. I'm too lazy to
ask it and then answer it, so will just put it here.
This is for the following query:
data = Leaderboard.objects.filter(id=custom_user.id).values(
'value1',
'value2',
'value3')
In template:
{% for dictionary in data %}
{% for key, value in dictionary.items %}
<p>{{ key }} : {{ value }}</p>
{% endfor %}
{% endfor %}

If you pass a variable data (dictionary type) as context to a template, then you code should be:
{% for key, value in data.items %}
<p>{{ key }} : {{ value }}</p>
{% endfor %}

I am thankful for the above answers pointing me in the right direction. From them I made an example for myself to understand it better. I am hoping this example will help you see the double dictionary action more easily and also help when you have more complex data structures.
In the views.py:
bigd = {}
bigd['home'] = {'a': [1, 2] , 'b': [3, 4] ,'c': [5,6] }
bigd['work'] = {'e': [1, 2] , 'd': [3, 4] ,'f': [5,6] }
context['bigd'] = bigd
In the template.html:
{% for bigkey, bigvalue in bigd.items %}
<b>{{ bigkey }}</b> <br>
{% for key, value in bigvalue.items %}
key:{{ key }} <br>
----values: {{ value.0}}, {{value.1 }}<br>
{% endfor %}
<br>
{% endfor %}
Notice the list in the second dictionary is accessed by the index in the list.
Result in browser is something like:

Related

Iterating through Python dictionary with Jinja2

I've scoured the internet and can't seem to find the solution that fits my case.
I have a dictionary:
{"1528430400000": 129, "1528516800000": 123.14, "1528603200000": 117.28, "1528689600000": 111.42, "1528776000000": 105.56, "1528862400000": 99.7, "1528948800000": 93.84, "1529035200000": 87.98, "1529121600000": 82.12, "1529208000000": 76.26, "1529294400000": 70.4, "1529380800000": 64.54, "1529467200000": 58.68, "1529553600000": 52.82, "1529640000000": 46.96, "1529726400000": 41.1, "1529812800000": 35.24, "1529899200000": 29.38, "1529985600000": 23.52, "1530072000000": 17.66, "1530158400000": 11.8, "1530244800000": 5.94, "1530331200000": 0.08, "1530417600000": 0}'
where each key is a javascript-formatted date.
I'm looking for a simple iteration through each key and value.
example:
{% for key,value in dict %}
{{key}}, {{value}}
{% endfor %}
Use:
{% for key, value in dict.items() %}
<h1>Key: {{key}}</h1>
<h2>Value: {{value}}</h2>
{% endfor %}
let's suppose your dictionary is "my_dict".
view.py (django) will have-
return render(request, 'template', { 'my_dict' :
my_dict })
HTML page will have-
{% for k,v in my_dict.items %}
{{ k }}: {{ v }} <br>
{% endfor %}
You can pass dict.items to the template rendering object:
return flask.render_template('template_name', data = the_dict.items())
Then, in the HTML:
{%for a, b in data%}
<span>Key: {{a}}, value: {{b}}</span>
{%endfor%}
{% if dict_var |type_debug == 'dict' %}
{% for key in dict_var %}
{{ key }}: "{{ dict_var[key] }}"
{% endfor %}
{% endif %}
use this will error: ValueError: too many values to unpack in sometimes
{% if dict_var |type_debug == 'dict' %}
{% for key, value in dict_var %}
{{ key }}: "{{ value }}"
{% endfor %}
{% endif %}

Recursively find child items and list in jinja

I'm trying to display "notes" in a nested list. Each note has a property called parentID that indicates a note that it is nested under.
Currently I am achieving a single level nest by doing this:
models.py
class Note(Model):
title = CharField()
tags = CharField()
content = TextField()
parentID = IntegerField(default=0)
class Meta:
database = db
app.py
def getSubnotes(note):
note_id = note.id
subnotes = models.Note.select().where(models.Note.parentID == note_id)
return subnotes
app.jinja_env.globals.update(getSubnotes=getSubnotes)
Index.html
<div class="row">
<div class="medium-12 medium-centered">
<ul>
{% for note in notes %}
{% if note.parentID == 0 %}
<li>{{ note.title }}</li>
<ul>
{% for subnote in getSubnotes(note) %}
<li>{{ subnote.title }}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
</ul>
</div>
I would like to, however, recursively find all children notes of a single note and list them out, so there are nests of nests.
I have seen this as an example of how to recursively list in jinja (from jinja docs):
<ul class="sitemap">
{%- for item in sitemap recursive %}
<li>{{ item.title }}
{%- if item.children -%}
<ul class="submenu">{{ loop(item.children) }}</ul>
{%- endif %}</li>
{%- endfor %}
</ul>
However I am confused about what .children actually is. How is it referencing itself or items of the same type?
How would I go about doing this recursively or is there a better method for achieving the same thing?
Any help is very much appreciated!
In the example from the docs, I think that item.children is just an iterable of items of the same type. Then {{ loop(item.children) }} causes the current loop to be executed over the iterable item.children creating a nested list.
You can verify this:
import jinja2
templ = """
{%- for item in items recursive %}
{{item.name}}
{%- if item.children %}
{{- loop(item.children) }}
{%- endif %}
{%- endfor %}
"""
items = [{'name': 'Bobby'},
{'name': 'Jack',
'children': [
{'name': 'Jake'},
{'name': 'Jill'}]},
{'name': 'Babby', 'children': []}]
template = jinja2.Template(templ)
print(template.render(items=items))
prints out
Bobby
Jack
Jake
Jill
Babby
So in your example, I think you should be able to do something like
<div class="row">
<div class="medium-12 medium-centered">
<ul>
{% for note in notes recursive %}
{% if note.parentID == 0 %}
<li>{{ note.title }}</li>
<ul>
{{ loop(getSubnotes(note)) }}
</ul>
{% endif %}
{% endfor %}
</ul>
</div>
as long as getSubnotes(note) returns empty if the note has no subNotes.
Even more complete, in my opinion (it explores lists and dictionaries inside lists):
<dl class="row">
{% for key, value in json.items() recursive %}
{% set outer_loop = loop %}
<dt class="col-3">{{ key }}</dt>
<dd class="col-9">
{% if value is string %}
{{ value }}
{% elif value is mapping %}
<dl class="row">
{{ loop(value.items()) }}
</dl>
{% elif value is iterable %}
<ol>
{% for item in value %}
<li>
{% if item is mapping %}
<dl class="row">
{{ outer_loop(item.items()) }}
</dl>
{% else %}
{{ item }}
{% endif %}
</li>
{% endfor %}
</ol>
{% else %}
{{ value }}
{% endif %}
</dd>
{% endfor %}
</dl>
I wonder if/how could be simplified.

How to tell list from non-list in Django template?

I've got a Django template I'd sometimes like to pass a list and sometimes like to pass a single value. How can the template tell which it was given?
I'm thinking the value would be set like one of these:
context = {
'foo' : 'bar
}
or:
context = {
'foo' : ['bar', 'bat', 'baz']
}
Then, the template would have code that looks something like this:
{% if foo isa list %}
{% for item in foo %}
{{ item }}<br>
{% endfor %}
{% else %}
{{ item}}<br>
{% endif %}
I can set it up to have foo or foolist, for example, and check for one or the other. However, it'd be a bit nicer (imo) to just have foo that was either a list or not.
If you intend to do it this way then just add a check that it doesn't have format(in case of string) method and has 0 index, if so then its a list else considered single value
{% if foo.0 and not foo.format %}
{% for item in foo %}
{{ item }}<br>
{% endfor %}
{% else %}
{{ item}}<br>
{% endif %}
I think your approach is needlessly complicated.
I would just go with a list:
views.py
foo_list = ['bar']
context = {
'foo': foo_list,
'foo_len': len(foo_list),
}
template
{% if foo_len == 1 %}
{{ foo.0 }}
{% else %}
{% for item in foo %}
{{ item }}
{% endfor %}
{% endif %}

Loop over dictionary of dictionaries in Django Template for 1 line of code

The dictionary I'm passing to the Django template contains 2 dictionaries, each with a list:
'nav_dict': {
'class_name': ['Chemical', 'Avian', 'Mammal'],
'tab_label': ['Chemical!', 'Avian!', 'Mammal!']
}
I want to loop over the lists in each dict to fill out this line of code:
<li class="{{ item_className }} tabSel">{{ item_tabLabel }}</li>
where item_className = each value in the class_name list and item_tabLabel = each value in the tab_label list. The result would 3 <li> tags with a class_name and tab_label.
I have tried something like this (This code only handles the class_name part), but I can't get the loops to append to the same line of code (each <li>):
{% for key, value in nav_dict.items %}
{% if key == 'class_name' %}
{% for item_className in value %}
{% if forloop.counter0 == 0 %}
<li class="{{ item_className }} tabSel">{{ item_tabLabel }}</li>
{% else %}
<li class="{{ item_className }} tabUnsel">{{ item_tabLabel }}</li>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
The problem you have is with the way you are presenting your data.
Why don't you create your dictionary like this, where each key is the class name and the associated value is the label. It would be more semantic and readable.
'nav_dict': {
'Chemical': 'Chemical!',
'Avian': 'Avian!',
'Mammal': 'Mammal!,
}
Then you can just loop over this and place the key as the class attribute, and the value as the label attribute.
{% for key, value in nav_dict.items %}
{% if forloop.counter0 == 0 %}
<li class="{{ key }} tabSel">{{ value }}</li>
{% else %}
<li class="{{ key }} tabUnsel">{{ value }}</li>
{% endif %}
{% endfor %}
If the order of the elements is important (as dictionaries are un-ordered), you could use an OrderedDict from the collections module to retain insertion order. You would do something like this inside your view...
>>> from collections import OrderedDict
>>> nav_dict = OrderedDict(zip(['Chemical', 'Avian', 'Mamma!'], ['Chemical!', 'Avian!', 'Mammal!']))
OrderedDict([('Chemical', 'Chemical!'), ('Avian', 'Avian!'), ('Mammal', 'Mammal!')])
Similarly you could use a list of tuples as your data
'nav_list': [('Chemical', 'Chemical!'), ('Avian', 'Avian!'), ('Mammal', 'Mammal!')]
And loop over this object like so
{% for class_name, label_name in nav_list %}
{% if forloop.counter0 == 0 %}
<li class="{{ class_name }} tabSel">{{ label_name }}</li>
{% else %}
<li class="{{ class_name }} tabUnsel">{{ label_name }}</li>
{% endif %}
{% endfor %}
If you only want to append an exclamation mark to your string to create the label, you could of course create a custom template filter instead - or just append the exclamation mark inside the template itself.
If you have to use that dictionary, you can use this template code:
{% for item_className in nav_dict.class_name %}
{% with forloop.counter0 as index_className %}
{% for item_tabLabel in nav_dict.tab_label %}
{% with forloop.counter0 as index_tabLabel %}
{% ifequal index_className index_tabLabel %}
{% if index_className == 0 %}
<li class="{{ item_className }} tabSel">{{ item_tabLabel }}</li>
{% else %}
<li class="{{ item_className }} tabUnsel">{{ item_tabLabel }}</li>
{% endif %}
{% endifequal %}
{% endwith %}
{% endfor %}
{% endwith %}
{% endfor %}

Django view: How to display data from a dictionary

I've got a dictionary like {'a':{'c':2, 'd':4 }, 'b': {'c':'value', 'd': 3}}
How can I display this into a table in view?
Question is answered here:
In summary you access the code as you would for a python dictionary
data = {'a': [ [1, 2] ], 'b': [ [3, 4] ],'c':[ [5,6]] }
You can use the dict.items() method to get the dictionary elements:
<table>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
</tr>
{% for key, values in data.items %}
<tr>
<td>{{key}}</td>
{% for v in values[0] %}
<td>{{v}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
Depends on how you want to do it. In Django templates, you access keys the same way you access a method. That is, Python code like
print my_dict['a']['c'] # Outputs: 2
becomes
{{ my_dict.a.c }} {# Outputs: 2 #}
in Django templates.
Had a similar problem and I solved it this way
PYTHON
views.py
#I had a dictionary with the next structure
my_dict = {'a':{'k1':'v1'}, 'b':{'k2': 'v2'}, 'c':{'k3':'v3'}}
context = {'renderdict': my_dict}
return render(request, 'whatever.html', context)
HTML
{% for key, value in renderdict.items %}
<h1>{{ key }}</h1>
{% for k, v in value.items %}
<h1>{{ k }}</h1>
<h1 > {{ v }}</h1>
{% endfor %}
{% endfor %}
The outputs would be
{{ key }} = a
{{ k }} = k1
{{ v }} = v1 #and so forth through the loop.

Categories