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>
Related
I have a long dictionary of data which looks like this,
('Item', 8): Components_data(base_quantity=63.0, items_data={'830927': [1.0, 14.851799999999999], '831103': [0.37170000000000003, 0.6972720300000002]}, price_labor=374.21824212, total=389.76731415)}
The key is a tuple and my values are in a namedtuple, with 3 integers and 1 dictionary where keys are strings and values are integers.
I want to use those values to build an Html table dynamically using jinja:
the result I want need to look like this:
Where the rows of components, Qty and Price unit are generated automatically according to the values of items_data in Componnents_data field.
here is what I have tried so far with jinja :
<table class="table table-bordered">
<thead>
<tr>
<th>Level</th>
<th>Item</th>
<th>Component</th>
<th>Qty</th>
<th>Price Unit</th>
<th>Price Total</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{% for item, components_data in prices.items() %}
<tr>
<td rowspan="3">{{item[1]}}</td>
<td rowspan="3">{{item[0]}}</td>
</tr>
{% for sub_components, sub_comp_dat in components_data.items_data.items()%}
<td>{{sub_components}}</td>
<td>{{ sub_comp_dat[0] }}</td>
<td>{{ sub_comp_dat[1] }}</td>
<td>{{ components_data.price_labor }}</td>
<td>{{ components_data.total }}</td>
</tr>
{% endfor %} {% endfor %}
<tr>
<td colspan="3" id='total-label'>Total</td>
<td colspan="4" id='total-value' text-align='right'>july</td>
</tr>
</tbody>
</table>
And the results looks like this :
I have tried every tip I know but cannot get the expected results, Any Help is welcome.
Thanks
I do not know the jinja syntax, but you can easily achieve your purpose storing a boolean value to check if the total has been already written.
e.g.:
{% for item, components_data in prices.items() %}
<tr>
<td rowspan="3">{{item[1]}}</td>
<td rowspan="3">{{item[0]}}</td>
</tr>
//set the flag to false
isFirstTime = false
{% for sub_components, sub_comp_dat in components_data.items_data.items()%}
<td>{{sub_components}}</td>
<td>{{ sub_comp_dat[0] }}</td>
<td>{{ sub_comp_dat[1] }}</td>
//show the price only the first time
if( isFortTime)
{
isFistTime = true;
<td rowspan="3">{{ components_data.price_labor }}</td>
<td rowspan="3">{{ components_data.total }}</td>
}
</tr>
{% endfor %}
{% endfor %}
Again this is not the correct syntax but you can achieve this with no problem.
Documentation:
Assign a variable in the template
If Statement
Thanks again #Alessandro.Vegna answer for the intuition of using if else statement.
It can be achieved according to this answer by using namespaces: in jinja 2.0
here is the answer :
<tbody>
{% for item, components_data in prices.items() %}
<tr>
<td rowspan="3">{{item[1]}}</td>
<td rowspan="3">{{item[0]}}</td>
</tr>
{% set time = namespace(first=False) %}
{% for sub_components, sub_comp_dat in components_data.items_data.items() %}
<tr>
<td>{{sub_components}}</td>
<td>{{ sub_comp_dat[0] }}</td>
<td>{{ sub_comp_dat[1] }}</td>
{% if not time.first %}
{% set time.first = True %}
<td rowspan="3">{{ components_data.price_labor }}</td>
<td rowspan="3">{{ components_data.total }}</td>
{% endif %}
</tr>
{% endfor %} {% endfor %}
<tr>
<td colspan="3" id='total-label'>Total</td>
<td colspan="4" id='total-value' text-align='right'>july</td>
</tr>
</tbody>
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 %}
I have two lists in python that I would like to input into two separate columns in an HTML table. What would the code look like on the python end of things and what would it look like for html?
This is what I have in python now:
giver = []
recipient = []
giver.append(name)
recipient.append(match)
return render_template("created.html", givers=givers, recpients=recipients)
And this is what I have in HTML:
<table>
<thead>
<tr>
<th>Giver</th>
<th>Recipient</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ givers }}</td>
<td>{{ recipients }}</td>
</tr>
</tbody>
</table>
Create one list
data = []
data.append( (name, match) )
return render_template("created.html", data=data)
and use it in template
{% for row in data %}
<tr>
<td>{{ row[0] }}</td>
<td>{{ row[1] }}</td>
</tr>
{% endfor %}
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>
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]