Jinja2 List of Dictionaries into HTML Table? - python

So im trying to create an HTML table using Jinja2 from a list of dictionaries (as returned by a Flask SQL select statement).
Right now test_list has stored a list of dictionaries (with the key's being the DB columns).
Right now im using this:
<table style="width:100%">
{% for dict_item in history_list %}
{% for key, value in dict_item.items() %}
<tr>
<th> {{ key }} </th>
<td> {{ value }} </td>
</tr>
{% endfor %}
{% endfor %}
</table>
It does work, but it's basically producing 2 columns (one being the keys and one being the columns). Im wanting to get the DB keys as columns titles in the table and then just the values placed into each column.
Is this possible? since I would want to iterate through the key's just once?

You need something like this, that provides a header row of th elements, then proceedes to the data rows (the body of the table).
<table style="width:100%">
<!-- table header -->
{% if history_list %}
<tr>
{% for key in history_list[0] %}
<th> {{ key }} </th>
{% endfor %}
</tr>
{% endif %}
<!-- table rows -->
{% for dict_item in history_list %}
<tr>
{% for value in dict_item.values() %}
<td> {{ value }} </td>
{% endfor %}
</tr>
{% endfor %}
</table>

Related

HTML table from python dictionary

I am trying to modify part of code in a flask application. What the flask app does so far:
It has around 20 links, when someone clicks on the link it returns .json objects (formed by python dictionaries via jsonify).
What I am trying to do:
Return the same results in a table format that can be potentially extracted to .csv
I created the following function:
def tab_out(output = {}):
return render_template('output_tab.html',output=output)
that sends the dictionary out to an html page, that contains this:
{% block content %}
<body>
<pre>
<table>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
<th>Header 5</th>
<th>Header 6</th>
</tr>
{% for key_1, value in output.items() %}
{% for key in value.keys() %}
<tr>
<td>
{{ key_1 | safe }}
</td>
<td>
{{ key | safe }}
</td>
<td>
{{ value[key]["Header_3"] }}
</td>
<td>
{{ value[key]["Header_4"] }}
</td>
<td>
{{ value[key]["Header_5"] }}
</td>
<td>
{{ value[key]["Header_6"] }}
</td>
</tr>
{% endfor %}
{% endfor %}
</table>
</pre>
</body>
{% endblock %}
What's the issue:
I need to make it dynamic.
Each page has different headers.
In each page the resulted .json comes from a dictionary that has sub-dictionaries and the number of keys in each dictionary can be different. So I can't specify the headers before hand. I want them dynamically created. Maybe flatten out the dictionary (up to a level 2 let's say) if there's 3 sub-dictionaries and get the results as headers and the rest as values.
I've read a couple similar questions in sa, but none of them really helped me. Any ideas?
The jinja code below will generate HTML table from any FLAT dict.
The headers are dynamic. entry_list is a list of dicts. Your code should create a flat dict.
<table style="width:100%">
<!-- table header -->
{% if entry_list %}
<tr>
{% for key in entry_list [0] %}
<th> {{ key }} </th>
{% endfor %}
</tr>
{% endif %}
<!-- table rows -->
{% for dict_item in entry_list %}
<tr>
{% for value in dict_item.values() %}
<td> {{ value }} </td>
{% endfor %}
</tr>
{% endfor %}
</table>

Nesting a hyperlink in a table cell using jinja

My HTML table has 5 columns, and I am using jinja to dynamically render the amount of columns depending on the amount of data. I would like to nest a hyperlink in the 5th column for every row.
from flask import Flask,render_template
from time import time as t
app = Flask(__name__)
#app.route('/offers')
def offers():
data = (
("user1","btc","ltc",t(),"127.0.0.1:5000/offer/abcd"),
("user2","xrp","xmr",t(),"127.0.0.1:5000/offer/efgh"),
("user3","bch","ltc",t(),"127.0.0.1:5000/offer/hijk")
)
return render_template("offers.html", data = data)
HTML:
<html>
<body>
<table class="GeneratedTable">
<thead>
<tr>
<th>Name</th>
<th>Have</th>
<th>Want</th>
<th>Created</th>
<th>Link</Link></th>
</tr>
</thead>
<tbody>
{% for row in data %}
<tr>
{% for cell in row %}
<td>{{cell}}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</body>
</html>
This will create the table, however the links (127.0.0.1:5000/offers/xxxx) will not be hyperlinks. How do I only make the final column a hyperlink using the links provided by the dataset? thanks.
Jinja does not recognise URL by default. You still need to manually format it. There are 2 ways to do that.
You can prepare the data in HTML format such as
data = (
("user1","btc","ltc",t(),"<a href=xxx>127.0.0.1:5000/offer/abcd</a>"),
("user2","xrp","xmr",t(),"127.0.0.1:5000/offer/efgh"),
("user3","bch","ltc",t(),"127.0.0.1:5000/offer/hijk")
)
Or you can format it in jinja template as below:
<tbody>
{% for row in data %}
<tr>
{% for cell in row %}
<td>
{% if loop.index0 != 4 %}
{{cell}}
{% else %}
<a href={{ cell }}>{{ cell }}</a>
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
Here the key is to use Jinja syntax loop.index0 to get the index number of row.

python flask : How to add a clickable column to the table and record it in the database after the operation

<h3>Out of severice vehicles</h3>
<table class="table table-hover">
<tbody>
<tr>
{% for col in caidian_oos.columns %}
<th>
{{col}}
</th>
{% endfor %}
</tr>
{% for row in caidian_oos.values %}
<tr>
{% for cell in row %}
<td>
{{cell}}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<br />
--
The data object is a pandas dataframe
I want to add a column that user can click.
On user's click it should save the corresponding row to mysql database.

How can I show in django list of records from db

Can anybody help me? I have a list of 60 records from django database in my html file. I want to show that list in table of 6 columns and 10 rows. In html file I used command {% for %} but the list is in one column.
My html file is:
{% for kategoria in kategorie %}
<table>
<tr>
<th> {{ kategoria.glowna|linebreaksbr }} ({{ wpisy_kat }}) </th>
</tr>
</table>
{% endfor %}
you can try using divisibleby template tag in your template like this to change row after every six entries.
remember {{ forloop.counter }} {# starting index 1 #} and {{ forloop.counter0 }} {# starting index 0 #}
{% for kategoria in kategorie %}
<table>
{% if not forloop.counter0 |divisibleby:"6" %}
<tr>
{% endif %}
<th> {{ kategoria.glowna|linebreaksbr }} ({{ wpisy_kat }}) </th>
{% if forloop.counter|divisibleby:"6" %}
</tr>
{% endif %}
</table>
{% endfor %}
<table>
{% for object in queryset %}
<tr>
<td> object.attr1 </td>
<td> object.attr2 </td>
<td> object.attr3 </td>
<td> object.attr4 </td>
<td> object.attr5 </td>
<td> object.attr6 </td>
</tr>
{% endfor %}
</table>
If you want to have a more pages with 10 items each page, have a look at django's pagination

Color coding cells in a table based on the cell value using Jinja templates

I have a simple flask app and need to display a table of values, with the cell backgrounds colour coded based on the cell value according to thresholds. I'm generating the table content as follows:
{% block dashboard_table2 %}
<table>
{% for row in data %}
{% for item in row %}
<td>{{ item }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endblock %}
I tried wrapping the values in style tags like this in Python but it didn't work:
if int(value) <= 10:
value = '<p style="background-color:Red">' + value + '</p>'
I'm guessing the CSS for the page is overriding the style attribute. I also tried just setting the text color attribute instead of background-color but no dice. Any suggestions on a good way to do this? I'd like to have a concise way to specify threshold values that aren't hard-coded in the templates.
The easiest way would be to put this display logic in your template:
<table>
{% for row in data %}
<tr>
{% for item in row %}
{% if item <= 10 %}
<td class="under-limit">{{ item }}</td>
{% else %}
<td>{{ item }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</table>
Then, in your CSS you can use:
.under-limit { background-color: red; }
<table>
{% for row in row %}
{% if item <= 10 %}
<tr style ="background-color: red">
<td> {{ item }} </td>
</tr>
{% else %}
<tr>
<td> {{ item }} </td>
</tr>
{% endif %}
{% endfor %}
</table>
This works for me.

Categories

Resources