Display dict index or key name in django template - django

How do I traverse and display the dict "index name" or "key name" in Django Template? Below is the dict from the context.
Basically this is the structure of my dict all_options[category][sub_category][name]. "Category, sub_Category and name" are dynamic. I wanted to display "Category" first then drill down to "Sub Category" then drill further down.
Templates doesn't allow using square braces to access the dict attribute.
Thanks in advance!
Context
'Condenser (WC)': {
'Water Box': {
'2MPA Condenser Water Box': {
'option': '2MPA Condenser Water Box',
'chillers': [{
'chiller': 'xxxxxxxxxxx',
'factory': '2' ,
'option': 'WB240.2U.F2HVKA>
}, {
'chiller': 'xxxxxxxxxxx',
'factory': '1' ,
'option': 'WB088.2H.F2AYFA>
}]
},
},
'Anodes': {
'Magnesium Anodes': {
'option': 'Magnesium Anodes',
'chillers': [{
'chiller': 'xxxxxxxxxxx',
'factory': '2' ,
'option': 'WB240.2U.F2HVKA>
}, {
'chiller': 'xxxxxxxxxxx',
'factory': '2' ,
'option': 'WB240.2U.F2HVKA>
}]
}
},
'Stainless Steel Tube Sheet': {
'304 SS Condenser Tube Sheets': {
'option': '304 SS Condenser Tube Sheets',
'chillers': [{
'chiller': 'xxxxxxxxxxx',
'factory': '2' ,
'option': 'WB240.2U.F2HVKA>
}]
},
}
},
Template
In the template, I added a comment and it's the string that needs to be printed.
{% for category_name in all_options %}
{{ category_name }} #Condenser (WC)
{% for subcat in category_name %}
{{ subcat }} #Water Box
{% for item in subcat %}
{{ item }} #2MPA Condenser Marine Water Box
{% for chiller in item.chillers %}
{{ chiller.option }} #WB200.3K.F2HVKA
{% endfor%}
{% endfor%}
{% endfor%}
{% endfor %}

In Python you can iterate over a iterable if 2-tuples, by calling the .items() function on the dictionary. In Django templates, we can do this as well:
{% for category_name, category in all_options.items %}
{{ category_name }} #Condenser (WC)
{% for subcat_name, subcat in category.items %}
{{ subcat_name }} #Water Box
{% for item_name, item in subcat.items %}
{{ item_name }} #2MPA Condenser Marine Water Box
{% for chiller in item.chillers %}
{{ chiller.option }} #WB200.3K.F2HVKA
{% endfor%}
{% endfor%}
{% endfor%}
{% endfor %}
(or something similar to this)
So here category_name is the key associated with the the dictionary item, and category is the value (so in this case a dictionary as well*). You can then for example enumerate again over that dictionary, and so on.
Note that in Python dictionaries are unordered: so that means that iteration can happen in any order possible. In case you want a fixed order, I advice you to use a list of 2-tuples, in which case you do not have to call .items of course. Furthermore a dictionary can contain only hashable keys, and every key can occur at most once. This is not because of Django, it is simply how dictionaries are designed in Python.
As said before, in case you want an ordered collection of elements such that the "key" does not has to be hashable and/or occur multiple times, I would advice you to use a list of 2-tuples (something like [(k1, v1), (k2, v2)] with ki the key, and vi the corresponding value).
In case you are only interested in the values, you can use .values, which will produce an iterable over the values of the dictionary.

Related

How to display a multi layer JSON in Django template?

So I have this JSON response:
{
"orders": [
{
"orderId": "4123456789",
"dateTimeOrderPlaced": "2017-02-09T12:39:48+01:00",
"orderItems": [
{
"orderItemId": "2012345678",
"ean": "0000007740404",
"cancelRequest": false,
"quantity": 10
}
]
}
]
}
I passed it in my view with the .json() method. I use this in my template:
{% for key, value in orders.items %}
{{ key }}: {{ value }}
{% endfor %}
I get this in my HTML:
orders: [{'orderId': '2529081520', 'dateTimeOrderPlaced': '2019-09-07T00:12:16+02:00', 'orderItems': [{'orderItemId': '2298728074', 'ean': '8945005881389', 'cancelRequest': False, 'quantity': 1}]}]
But how to dissect it further? For example to get the OrderId or the ean?
You can access dictionary items with the template variable dot-notation, like this
{% for order in orders.orders %}
{{ order.orderId }}
{% for item in order.orderItems %}
{{ item.ean }}
{% endfor %}
{% endfor %}
Assuming the context variable orders contains your parsed JSON, this template would be rendered like this:
OrderId: 4123456789
EAN: 0000007740404

Django template: access inner dictionary

A newbie django template question, hope to get some pointers.
I'm passing back a dictionary to render to html for a page. The structure of the dictionary is like the following:
dic:{
"names":["name1", "name2", "name3"],
"names1":{
"addresses":["address1","address2","address3"],
"key2":[......]
......
}
"name2":{......}
}
How do I access the inner dictionaries? The only way to know the keys for those inner dictionaries is from the list, but I was unable to iterate through values pointed by key "names" and use that value as a key to get the other dictionary. I have looked into writing customer filters/tags but not sure exactly how to proceed.
Use items, from django docs:
{% for key, value in data.items %}
{{ key }}: {{ value }}
{% endfor %}
I tested it with your example:
In template:
<ul>
{% for l1_key, l1_value in dic.items %}
<li>{{ l1_key }}:
<ul>
{% for l2_key, l2_value in l1_value.items %}
<li>{{ l2_key }}: {{ l2_value }}</li>
{% empty %}
<li>{{ l1_value }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
This will output something like:
- name2:
- address: [1, 2, 3]
- names:
- ['name1', 'name2', 'name3']
- names1:
- key2: [1, 2]
- addresses: ['address1', 'address2', 'address3']
items return a list of tuples formed by (key, value)
I used this dic (fix minor problems in your example):
dic = {
"names":["name1", "name2", "name3"],
"names1":{
"addresses":["address1","address2","address3"],
"key2":[1,2]
},
"name2":{'address':[1,2,3]}
}

Django templates, how to make a list of item's values from list of items

I have list of items:
items = [item1, item2, ...]
where
item1 = {'name': 'item1', 'value': 1} and so on.
In templates i have a list of these items: {{ items }}
How can i get a list [item1.name, item2.name, ...] in templates?
In your view, just add .values_list('name', flat=True) to your queryset. Now you are passing a list of item names to your template.
Other options:
Use a for loop to iterate over items.
Make a custom template tag.
If your just want to iterate the names in items:
{% for item in items %}
<p>name: {{item.name}}</p>
{% endfor %}
You can iterate over the items like that, in a for:
{% for item in items %}
<p>Name: {{ item.name }}</p>
<p>Value: {{ item.value }}</p>
{% endfor %}
You can't "create" variables in the Django Template Engine, but you can do it in your View:
items_names = [x['name'] for x in items]
And then access the items_names in your template.

Django regroup of cursor results

Using Django, I have a fairly complex SQL query that is working fine and returning the results I want, so I am not keen to try to reproduce this using Django's model query notation.
I am passing my results to my template and am able to display them using the following notation:
{% for line in myresults %}
...
{{ line.0 }}
...
{{ line.1 }}
etc.
{% endfor %}
Is there any way to use the regroup tag on this result set?
If I try:
{% regroup myresults by myresults.0 as mylist %}
{% for item in mylist %}
{{ item.grouper }}
{% for line in item.list %}
...
{{ line.0 }}
{{ line.1 }}
etc.
I get all of the results as before (without any regrouping) but don't get the item.grouper (all I see is "None" as a single group rather than my multiple groups)
Is this a syntax issue or am I trying something that doesn't fit regroup's capabilities?
I have used regroup in the normal way with a list of objects, but the above has me stumped.
Any suggestions? Thanks in advance.
with {% regroup myresults by myresults.0 as mylist %} you group by the first item in the list myresults you must group by some field of the items.
Next example from here:
cities = [
{'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'},
{'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'},
{'name': 'New York', 'population': '20,000,000', 'country': 'USA'},
{'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'},
{'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'},
]
...and you'd like to display a hierarchical list that is ordered by country, like this:
India
Mumbai: 19,000,000
Calcutta: 15,000,000
USA
New York: 20,000,000
Chicago: 7,000,000
Japan
Tokyo: 33,000,000
You can use the {% regroup %} tag to group the list of cities by country. The following snippet of template code would accomplish this:
{% regroup cities by country as country_list %}
<ul>
{% for country in country_list %}
<li>{{ country.grouper }}
<ul>
{% for item in country.list %}
<li>{{ item.name }}: {{ item.population }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>

How to iterate over nested dictionaries in django templates

I'm not sure the most efficient way to iterate over my nested dictionaries to print a matrix of the total and good values for every fruit for each date. Take for instance the two lists and dictionary below:
fruits = ['apples','oranges','bananas']
harvest_dates = ['2011-07-23','2011-07-22','2011-07-21']
harvest_data = {
'apples': {
'2011-07-23': {
'total': 100,
'good': 80},
'2011-07-22': {
'total': 97,
'good': 92},
'2011-07-21': {
'total': 90,
'good': 85}
},
'oranges': {
'2011-07-23': {
'total': 86,
'good': 82},
'2011-07-22': {
'total': 90,
'good': 75},
'2011-07-21': {
'total': 92,
'good': 92}
},
'bananas': {
'2011-07-23': {
'total': 10,
'good': 9},
'2011-07-22': {
'total': 12,
'good': 11},
'2011-07-21': {
'total': 9,
'good': 9}
}
}
I can easily do this in python:
for fruit in fruits:
for day in harvest_dates:
print "harvest: %s" % harvest_data[fruit][day]['total']
print "good crop: %s" % harvest_data[fruit][day]['good']
But I don't know how to access this data in django templates. I had been trying something such as:
{% for fruit in fruits %}
...
{% for day in harvest_dates %}
...
{{ harvest_data.fruit.day.total }}
{{ harvest_data.fruit.day.good }}
...
{% endfor %}
{% endfor %}
But it's simply not working.
{% for fruit in fruits %}
{{ harvest_data.fruit }} <--- this does not exist
{{ harvest_data[fruit] }} <--- this does not work
{% endfor %}
I'm a complete amateur and I'm probably going about this all wrong, but I've Google'd quite a bit and it's not clear to me what the best approach to getting the data I want is.
Since you're familiar with python, the following is logically how you would want to iterate through your dictionary in a Django template:
for key,value in harvest_data.items():
... print key
... for key2,value2 in value.items():
... print key2
... for key3,value3 in value2.items():
... print "%s:%s"%(key3,value3)
In your template, this translates as follows:
{% for key, value in harvest_data.items %}
{{ key }} <br>
{% for key2,value2 in value.items %}
{{ key2 }} <br>
{% for key3, value3 in value2.items %}
{{ key3 }}:{{ value3 }} <br>
{% endfor %}
{% endfor %}
{% endfor %}
The Django docs actually briefly include an example of how to iterate through dictionaries when describing how the for template tag works:
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#for
as rolling stone says thats the way to iterate over dictionaries in templates, i would only change the key, value keywords for different keywords in every iteration like this:
{% for key, value in harvest_data.items %}
{{ key }} <br>
{% for key2,value2 in value.items %}
{{ key2 }} <br>
{% for key3, value3 in value2.items %}
{{ key3 }}:{{ value3 }} <br>
{% endfor %}
{% endfor %}
{% endfor %}
just for the sake of clarity :)
And if you want to line up your values i would suggest you use another data structure where you can sort by date, for example a something like this:
{ 'oranges' : [(date1, value1), (date2,value2)] ...}
Try to do the least possible operations in your templates, so dont do a sort or nested if's if you dont have to
Really old question, but I will add my 1.5c.
This is a good use case of the regroup tag (https://docs.djangoproject.com/en/1.9/ref/templates/builtins/#regroup) and a bit of data refactoring:
Have your data as a simple list of data points:
harvest_data = [
{'fruits': 'apples', 'date': '2011-07-23', 'total': 100, 'good': 80},
# ...
]
In your template, group by the chosen dimension(s):
{% regroup harvest_data by fruits as data_by_fruits %}
{% for data in data_by_fruits %}
<h1>{{ data.grouper }}</h1> # 'apples'
{% regroup data.list by date as data_by_fruits_date %}
{% for data_1 in data_by_fruits_date %}
<h2>{{ data_1.grouper }}</h2> # '2011-07-23'
{% for datapoint in data_1.list %}
total: {{ datapoint.total }} <br/>
good: {{ datapoint.good }} <br/>
{% endfor %}
{% endfor %}
{% endfor %}