jinja2: building table by iterating down columns instead of across rows - python

If I have the following lists:
headers = ['Name', 'Age']
rows = [['Johnny', 30], ['Zack', 20]]
I can easily make a table via Jinja2 (https://jsfiddle.net/equbh9du/1/):
<table class="table table-bordered table-hover">
<thead>
<tr>
{% for h in headers %}
<td>{{ h }}</td>
{% endfor %
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr>
{% for item in row %}
<td>{{ item }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
I'm noticing it's much easier (and more organized) to return my data as a dictionary:
d = {'Name': ['Johnny', 'Zack'], 'Age': [30, 20]}
Is there an easy way to build the table I built above using this dict. I imagine I need to finish the iteration down each column before continuing to the next column (in the example above I finish the iteration across each row before continuing to the next row).
This is the code I have so far but I'm getting a messed up table (https://jsfiddle.net/j164fqy9/1/):
<table class="table table-bordered table-hover">
<thead>
<tr>
{% for h in d %}
<td>{{ h }}</td>
{% endfor %
</tr>
</thead>
<tbody>
{% for h, col_values in d.items() %}
{% for item in col_values %}
<tr>
<td>{{ item }}</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
EDIT: If HTML standard prevents iterating down columns first, then I need to construct the headers and rows from d. Is below the best way to do this?
headers = [h for h in d]
rows = [[l[i] for h, l in d.items()] for i in range(len(d['Name']))]

If you allways have the same number of items in col_values this should work fine :
{% for i in range(d['Name']|count) %}
<tr>
{% for k in d %}
<td>{{ d[k][i] }}</td>
{% endfor %}
</tr>
{% endfor %}

Related

Iterating over a list from an object in Django template

I am trying to iterate over a list that is below an object in a Django template.
Unfortunately I am not getting anywhere.
This is the object:
{'Value1': [8, 5, 4, 7, 4, 5], 'Value2': [], 'Value3': []}
I am doing in the template something like:
{% for entry in data %}
<tr>
<td>{{ entry }}</td>
<td>{{ entry.0 }}</td>
</tr>
{% endfor %}
or
{% for entry in data %}
<tr>
<td>{{ entry }}</td>
{% for i in entry %}
<td>{{ i }}</td>
{% endfor %}
</tr>
{% endfor %}
But all I am getting is just the first letter of the key.
You have to look for both - keys and values in dict's items:
{% for key, value_list in data.items %}
<tr>
<td>{{ entry }}</td>
{% for value in value_list %}
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}
Did you try iterating over the items in your dict, like so?
{% for key, value in data.items %}

Iterate and print elements for 2d arrays in Jinja syntax

I want to iterate a 2d array to print every element in one cell each, how can I write this in jinja?
My code so far only prints each row (containing three elements) in a single cell:
Data: [[90,50,30],
[40,20,70],
[60,80,10]]
<div class="container">
<table class="table">
<thead>
<th>No</th>
<th>Value of Row 1</th>
<th>Value of Row 2</th>
<th>Value of Row 3</th>
</thead>
<tbody>
{% for i in array %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ i }}</td>
<td>{{ i }}</td>
<td>{{ i }}</td>
</tr>
{% endfor %}
</div>
Expected output:
No
Value of Row 1
Value of Row 2
Value of Row 3
1
90
50
30
2
40
20
70
3
60
80
10
Change your template to:
<div class="container">
<table class="table">
<thead>
<th>No</th>
<th>Value of Row 1</th>
<th>Value of Row 2</th>
<th>Value of Row 3</th>
</thead>
<tbody>
{% for row in data %}
<tr>
<td>{{ loop.index }}</td>
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</div>

How to iterate over a list value of a dictionary in django template

I have a dictionary where value are in list
{
'Fees': ['88000', '88000'],
'ROll Number': ['I0', 'I1'],
'Mark': [10, 10]
}
So I am trying to insert this data in table, SO my Django template are
<table>
<thead>
<tr>
{% for k, v in loan_bank_info.items %}
<th>{{ k }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
<tr>
{% for k, value in loan_bank_info.items %}
{% for v in value %}
<td>{{ v }}</td>
{% endfor %}
{% endfor %}
</tr>
</tbody>
</table>
but in table value are printing as follow,
Fees ROll Number Mark
88000 88000 I0 I1 10 10
But what I want is -
Fees ROll Number Mark
88000 I0 10
88000 I1 10
how to iterate over list value in Django template
You can just iterate over the list. Something like below
<tr>
{% for k, value in loan_bank_info.items %}
{% for v in value %}
{% for i in v %}
<td>{{ i }}</td>
{% endfor %}
{% endfor %}
{% endfor %}
</tr>

Jinja if statments

Hopefully someone can help me here..
Lets say I have column a, this column 'a' can have rows of all values. I need to get jinja to look at the data of this row and if it's below a specific value, to change the html (Lets not worry about that)
The below works fine. Both rows of data display as needed.
<table>
{% for row in data %}
<tr>
<td>{{ row['a'] }}</td>
<td>{{ row['b'] }}</td>
</tr>
{% endfor %}
</table>
How can I say for example:
for value in row a, if it's less than 50, do this, else, do this.
UPDATE: Can anyone see an issues with the following?
<table>
{% for row in data %}
<tr>
<td>{{ row['a'] }}</td>
{% if row['b'] <= 10 %}
<td><font color="#FF0000">{{ row['b'] }}</font></td>
{% else %}
<td>{{ row['b'] }}</td>
{% endif %}
<td>{{ row['c'] }}</td>
<td>{{ row['d'] }}</td>
<td>{{ row['e'] }}</td>
</tr>
{% endfor %}
</table>
Implementation of condition would be like this, You need to close the if block in the template.
<table>
{% for row in data %}
<tr>
{% if row['a'] <= 10 %}
<td class="test">{{ row['a'] }}</td>
{% else %}
<td> {{ row['a'] }} </td>
{% endif %}
</tr>
{% endfor %}
</table>

Changing a list output after a certain number of variables

I have a list:
c = [1,2,3,4,5,6,7,8]
in my template, I want to output this as follows:
<table>
<tr>
<td>1</td>
<td>2</td>
<td>...</td>
</tr>
</table>
<table>
<tr>
<td>5</td>
<td>...</td>
<td>8</td>
</tr>
</table>
What is the best way to do this?
If you'd like to make it more generic, you can also use the built in divisibleby tag
{% for value in c %}
{% if forloop.counter0|divisibleby:cut_off %}
<table>
<tr>
{% endif %}
<td>{{value}}</td>
{% if forloop.counter|divisibleby:cut_off %}
</tr>
</table>
{% endif %}
{% endfor %}
where c is the list and cut_off is the slicing number (e.g. 4 in your question). These variables are supposed to be sent the to the template in your view.
You can use slice template filter:
<table>
<tr>
{% for value in c|slice:":4" %}
<td>{{ value }}</td>
{% endfor %}
</tr>
</table>
<table>
<tr>
{% for value in c|slice:"4:" %}
<td>{{ value }}</td>
{% endfor %}
</tr>
</table>
Assuming c is passed in the template context.
slice basically follows usual python slicing syntax:
>>> c = [1,2,3,4,5,6,7,8]
>>> c[:4]
[1, 2, 3, 4]
>>> c[4:]
[5, 6, 7, 8]

Categories

Resources