Is there a way to specify different labels for the inner and outer ring in a nested pie/doughnut chart?
Example of nested pie chart with inner and outer pie/doughnut
In my specific example I am using the outer ring as a "detail view" (with many individual names) but I am using the inner ring to group together a number of the items - specifically, the "red" items in the outer ring are then grouped together for the inner ring. To this end I am looking to have the inner ring's red item named something like "group", but at present, since there are two items in the inner ring, the first two labels are being used.
Let me know if that makes sense or if more explanation is required!
For your reference here is the code used to generate the chart - the data itself is coming from a Flask app using the Jinja2 templating language, hence the {% for %} loops.
(I'm also VERY new to using ChartJS with Flask in this way so if there are best practices that I am ignoring/not aware of then please let me know!)
// Pie chart
const pieData = {
labels: ["99% of composers",
{% for c in one_percent_of_composers_list %}
{% for k,v in c.items() %}
'{{k}}',
{% endfor %}
{% endfor %}
],
datasets: [
{
// OUTER PIE
label: 'Performance Numbers',
data: [
{{everyone_else_performance_time}},
{% for c in one_percent_of_composers_list %}
{% for k,v in c.items() %}
{{v|round|int}},
{% endfor %}
{% endfor %},
],
backgroundColor: [
'rgb(54, 162, 235)',
{% for c in one_percent_of_composers_list %}
{% for k,v in c.items() %}
'rgb(193, 16, 36)',
{% endfor %}
{% endfor %}
],
hoverOffset: 4
},
{
// INNER PIE
label: 'Composer Numbers',
data: [
{{everyone_else_list|length}},
{{one_percent_of_composers_list|length}},
],
backgroundColor: [
'rgb(54, 162, 235)',
{% for c in one_percent_of_composers_list %}
{% for k,v in c.items() %}
'rgb(193, 16, 36)',
{% endfor %}
{% endfor %}
]
}
]
};
const pieConfig = {
type: 'doughnut',
data: pieData,
options:{
plugins:{
legend:{
position:'bottom'
}
}
},
plugins: [counter]
};
TIA!
Rich
Related
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 %}
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
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.
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 %}
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 %}