How to display a multi layer JSON in Django template? - django

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

Related

Accessing nested values in Django

I am trying to access values in my Django template (using Jinja2) from an API and am struggling quite a bit. I'm new to Python/Django/programming and am having a hard time navigating through this complex nested structure of lists/dicts.
Here is a snippet of the API response for a single flight (the response contains a total of 250 flights):
{
"meta": {
"count": 2
},
"data": [
{
"type": "flight-offer",
"id": "1",
"source": "GDS",
"instantTicketingRequired": false,
"nonHomogeneous": false,
"oneWay": false,
"lastTicketingDate": "2020-11-20",
"numberOfBookableSeats": 2,
"itineraries": [
{
"duration": "PT22H40M",
"segments": [
{
"departure": {
"iataCode": "GIG",
"terminal": "2",
"at": "2020-12-01T16:30:00"
},
"arrival": {
"iataCode": "CDG",
"terminal": "2E",
"at": "2020-12-02T07:45:00"
},
"carrierCode": "AF",
"number": "443",
"aircraft": {
"code": "77W"
},
"operating": {
"carrierCode": "AF"
},
"duration": "PT11H15M",
"id": "3",
"numberOfStops": 0,
"blacklistedInEU": false
},
{
"departure": {...
For each flight I would like to extract the following key/values:
id
duration
iataCode
Below is what I have tried so far...
id (successful)
{% for flight in data %}
{{ flight.id }}
{% endfor %}
iataCode (unsuccessful)
{% for flight in data %}
{% for itinerary in itineraries %}
{% for segment in segments %}
{{ departure.iataCode }}
{% endfor %}
{% endfor %}
{% endfor %}
iataCode (unsuccessful)
{% for itineraries, itinerary in data %}
{% for segments, segment in itineraries %}
{{ departure.iataCode }}
{% endfor %}
{% endfor %}
{% endblock %}
Would be very appreciative of any advice here.
Thank you!
You have to "follow" the loop variable.
{% for flight in data %}
{% for itinerary in flight.itineraries %}
{% for segment in itinerary.segments %}
{{ segment.departure.iataCode }}
{% endfor %}
{% endfor %}
{% endfor %}

How to use the current index to get the value of another array?

I've read this, and I have an array like that:
context[u'erreurs'] = {
'aa': {'titres': [], 'liste': [], 'urls': []},
'bb': {'titres': [], 'liste': [], 'urls': []},
'...': {'titres': [], 'liste': [], 'urls': []}
}
If there's an error, 'titres', 'liste' and 'urls' become array of strings, filled with adequates values.
In my template, if erreur is set I do this:
{% for idx, tab in erreurs.items %}
<ul>
{% for e in tab.liste %}
{% if user.is_authenticated %}
<li>{{ e }}</li>
{% else %}
<li>{{ e }}</li>
{% endif %}
{% endfor %}
</ul>
{% endfor %}
I would like to use the current index to use the value that is in another array, here: tab.urls. It doesn't work and gives me the error:
Could not parse the remainder: '[forloop.counter0]' from 'tab.urls[forloop.counter0]'
How to solve this?
Unfortunately, Django's templates don't support such syntax. You should put together a custom template filter:
# yourapp/templatetags/yourapp_tags.py:
from django import template
register = template.Library()
#register.filter
def at_index(array, index):
return array[index]
and use it like:
{% load yourapp_tags %}
{{ tab.urls|at_index:forloop.counter0 }}
You need to make an actual model that represents the data then the task becomes trivial
class YourModel(object):
titre = ''
liste = ''
url = ''
context[u'erreurs'] = {
'aa': [], # List of model
}
{% for idx, tab in erreurs.items %}
<ul>
{% for model in tab %}
{{ model.titre }}
{{ model.liste }}
{{ model.url }}
{% endfor %}
</ul>
{% endfor %}

Nested variable calls

Can something like this be done in django?
{% for item in lst %}
{{ something_{{ item }} }}
{% endfor %}
Args passed to render would be for example:
{"lst": range(3), "something_0": "aaa", "something_1": "aaa", "something_2": "aaa"}
No. Structure your data as a list of dicts.
[
{'something': 'aaa', 'something_else': 'bbb', ...},
{'something': 'ccc', 'something_else': 'ddd', ...},
...
]
and now:
{% for item in lst %}
{{ item.something }}
{{ item.something_else }}
{% endfor %}

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]}
}

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 %}