How to display contents of a dictionary into web page using Flask - python

I have this problem where I can't display the contents of a dictionary into a webpage.
web_indiv[url_sequence] = {'url' : converted_url , 'name' : x.name, 'count' : web_count_current }
return render_template('video.html', web_data = web_indiv)
The web_indiv is populated using a loop, and then passed to video.html as web_data.
Sample dictionary
{1: {'url': 'http://www.drpeppersnapplegroup.com/', 'name': 'Dr. Pepper-Snapple Group', 'count': 57}, 2: {'url': 'http://www.rccolainternational.com/', 'name': 'Royal Crown Cola', 'count': 41}}
Note: It is a dictionary that contains another dictionary inside it.
This is what I already have on my html file.
{% for key1,line in web_data.items() %}
{% for key2,line_item in line.items() %}
<tr>
<td class="col-md-2">{{ line_item['url'] }}</td>
<td class="col-md-2">{{ line_item['name'] }}</td>
<td class="col-md-2">{{ line_item['count'] }}</td>
</tr>
{% endfor %}
{% endfor %}
Data won't display on the webpage.
Thank you for taking time to read my query.

If it is just a dict, you could try this:
<html>
{{web_data[url_sequence]}}
<table>
<tr>
{%for value in web_data[url_sequence].values()%}
<td class="col-md-2">{{ value }}</td>
{% endfor %}
</tr>
</table>
</html>
Note that the web_data[url_sequence] is a dictionary.
This one will have the orders (url, name and then count):
<tr>
<td class="col-md-2">{{ web_data[url_sequence].url }}</td>
<td class="col-md-2">{{ web_data[url_sequence].name }}</td>
<td class="col-md-2">{{ web_data[url_sequence].count }}</td>
</tr>
Real example:
Suppose you have the dictionary web_indiv, then you want to render it to template video.html
#app.route('/', methods=['GET'])
def root():
web_indiv = {}
url_sequence = 'test'
web_indiv[url_sequence] = {'url':'testabc','name':'hello','count': 4}
return render_template('video.html', web_data = web_indiv, url_sequence = url_sequence)
Then you can use the dict in template like this:
<tr>
<td class="col-md-2">{{ web_data[url_sequence].url }}</td>
<td class="col-md-2">{{ web_data[url_sequence].name }}</td>
<td class="col-md-2">{{ web_data[url_sequence].count }}</td>
</tr>
The html will show you:
testabc hello 4

{% for key2,line_item in web_data[url_sequence].items %}
<tr>
<td class="col-md-2">{{ line_item }}</td>
</tr>
{% endfor %}

Related

loop.nextitem doesn't work with current value from data

I need to compare postback.campaign_id with the value of the next item. If it's similar, then, I don't print nothing, if not, then, print my row.
But, this code outputs everything.
<table>
<tr>
<td class="expand expand-campaign"><a>Test</a></td>
<td>{{ account_id }}</td>
</tr>
{% for postback in postbacks %}
{% if loop.nextitem is defined and postback.campaign_id != loop.nextitem[0] %}
<tr>
<td></td><td></td>
<td><input type="checkbox"></td>
<td class="expand expand-site"><a>{{ postback.campaign_id }}</a></td>
</tr>
{% endif %}
{% endfor %}
</table>
The loop.nextitem contains the whole variable in your next item. So, if it is a dictionary or object, like in your case, you can access its properties like the current object under loop.
In your case that would mean:
postback.campaign_id != loop.nextitem.campaign_id
You also have the issue that your last item will always be skipped by the condition loop.nextitem is defined. Since you are going to always print the last item of a streak of similar items, you can perfectly do:
{% if loop.nextitem is undefined
or postback.campaign_id != loop.nextitem.campaign_id
%}
Also note that, there is a loop.changed() construct in Jinja that can be handy in this specific use case.
So, with a list like:
postbacks = [
{'campagn_id': 1},
{'campagn_id': 2},
{'campagn_id': 2},
{'campagn_id': 3},
{'campagn_id': 3},
]
And this snippet of Jinja:
<table>
{%- for postback in postbacks %}
{%- if loop.changed(postback.campaign_id) %}
<tr>
<td class="expand expand-site">
{{ postback.campaign_id }}
</td>
</tr>
{%- endif %}
{%- endfor %}
</table>
It renders, with some style added for clarity, as:
table {
border-collapse: collapse;
}
td {
border: 1px solid;
padding: 4px;
}
<table>
<tr>
<td class="expand expand-site">
1
</td>
</tr>
<tr>
<td class="expand expand-site">
2
</td>
</tr>
<tr>
<td class="expand expand-site">
3
</td>
</tr>
</table>

How to separate database on 2 different table html

i have database for example
id
account_id
date
1
127
2022-04-25
2
128
2022-04-25
3
127
2022-04-24
4
128
2022-04-24
And i need separate this on 2 different tables:
account_id
date header
127
2022-04-25
127
2022-04-24
and the same with 128
That's my code for 1 table and i don't know how to separate
#bp.route('/')
def main():
wcms = Wcm.query.order_by(Wcm.date.desc()).all()
return render_template('table.html', wcms=wcms)
HTML:
<table class="table table-hover table-dark wcm">
<thead>
<tr>
<th>Date</th>
<th>WCM account ID</th>
<th>Number of standard tags</th>
<th>Number of extended tags</th>
</tr>
</thead>
<tbody>
{% for wcm in wcms %}
<tr>
<td>{{ wcm.date }}</td>
<td>{{ wcm.account_id }}</td>
<td>{{ wcm.nbm_stardart_tags }}</td>
<td>{{ wcm.nbm_custom_tags }}</td>
</tr>
{% endfor %}
</tbody>
</table>
For the following code to work we need to sort the data by the grouping value first. Since you want to seperate account IDs, I chose ASC.
wcms = Wcm.query.order_by(Wcm.account_id.asc(), Wcm.date.desc()).all()
The lambda returns the account ID to collect all entries into one list. groupby returns a list of tuples, the list() call is needed to evaluate the lazy iterator creating the group. The outer list comprehensions creates a list of those grouped Wcm lists.
wcms_by_account = [
list(wcm_group)
for acc_id, wcm_group
in groupby(wcms, lambda x: x.account_id
]
List strucure:
[
[
Wcm(account_id=127, date=2022-04-25, ...),
Wcm(account_id=127, date=2022-04-24, ...),
],
[
Wcm(account_id=128, date=2022-04-25, ...),
Wcm(account_id=128, date=2022-04-24, ...),
],
...
]
Then change your Web Template to handle a list of lists, creating a new table for each inner list.
{% for wcms in wcms_by_account %}
<table class="table table-hover table-dark wcm">
<thead>
<tr>
<th>Date</th>
<th>WCM account ID</th>
<th>Number of standard tags</th>
<th>Number of extended tags</th>
</tr>
</thead>
<tbody>
{% for wcm in wcms %}
<tr>
<td>{{ wcm.date }}</td>
<td>{{ wcm.account_id }}</td>
<td>{{ wcm.nbm_stardart_tags }}</td>
<td>{{ wcm.nbm_custom_tags }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}

How to display the keys of a python dictionary as HTML table headers and values of each key as a row under that table header?

I'm currently working in a django project in which I do some data analysis using pandas library and want to display the data (which is converted into a dictionary) as a HTML table.
dictionary that I want to display:
my_dict = {
'id': [1, 2, 3, 4, 5],
'product_name': [product1, product2, product3, product4, product5],
'value': [200, 400, 600, 800, 1000],
'available_qty': [1, 2, 3, 2, 4]
}
I want to display the above dictionary like this table in django template.
id
product_name
value
available_qty
1
product1
200
1
2
product2
400
2
3
product3
600
3
4
product4
800
2
5
product5
1000
4
I have tried the below code.
<table>
<thead><h2><b>my dictionary</b></h2></thead>
{% for key, values in my_dict.items %}
<th><b>{{ key }}</b></th>
{% for value in values %}
<tr>
{{value}}
</tr>
{% endfor %}
{% endfor %}
</table>
I get the results as,
(There is some space between each row displayed in the table)
Better first convert to list of rows (using zip()) and send this to template
my_dict = {
'id': [1, 2, 3, 4, 5],
'product_name': ['product1', 'product2', 'product3', 'product4', 'product5'],
'value': [200, 400, 600, 800, 1000],
'available_qty': [1, 2, 3, 2, 4]
}
all_headers = list(my_dict.keys())
all_rows = list(zip(*my_dict.values()))
print(all_headers)
for row in all_rows:
print(row)
Result:
['id', 'product_name', 'value', 'available_qty']
(1, 'product1', 200, 1)
(2, 'product2', 400, 2)
(3, 'product3', 600, 3)
(4, 'product4', 800, 2)
(5, 'product5', 1000, 4)
And then template could be (but I didn't test it)
<h2>my dictionary</h2>
<table>
<thead>
<tr>
{% for header in all_headers %}
<th>{{ header }}</th>
{% endfor %}
<tr>
</thead>
<tbody>
{% for row in all_rows %}
<tr>
{% for value in row %}
<td>{{ value }}</td>
{% endfor %}
<tr>
{% endfor %}
</tbody>
</table>
EDIT:
If you use pandas then you could use df.to_html() to generate table
import pandas as pd
df = pd.DataFrame(my_dict)
html_table = df.to_html(index=False)
print(html_table)
and it gives HTML similar to code from my previous template
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th>id</th>
<th>product_name</th>
<th>value</th>
<th>available_qty</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>product1</td>
<td>200</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>product2</td>
<td>400</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>product3</td>
<td>600</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>product4</td>
<td>800</td>
<td>2</td>
</tr>
<tr>
<td>5</td>
<td>product5</td>
<td>1000</td>
<td>4</td>
</tr>
</tbody>
</table>
And you can send html_table to template and you have to display it with option safe (so it will not convert < > to &lg;, >)
{{ html_table | safe }}
In your template
Load filters
{% load filter %}
{% block body %}
<table class="table table-hover">
<thead>
<tr>
{% for key in my_dict %}
<th scope="col">{{ key }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for i in my_dict|RANGE %}
<tr>
{% for key, value in my_dict.items %}
{% if forloop.counter0 < my_dict|length %}
<td>{{ value|items:i }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
In project/app/ create a folder called templatetags
In your templatetags folder there will be
init.py
filters.py
put the following code in filters.py
from django import template
register = template.Library()
#register.filter
def RANGE(dictionary):
length = 0
for key, value in dictionary.items():
if length < len(value):
length = len(value)
return list(range(length))
#register.filter
def items(List, index):
return List[index]

Reading a CSV file in Flask and iterating through Jinga2

I am trying to display data on my web app from a CSV file using Flask. The below code reads my CSV file and assigns stocklist as the variable for my data. In the HTML code below it, using jinga logic, I iterate through stocklist however my CSV columns are returned as rows (see sample output and pic). How do I display the rows correctly?
My python function:
#app.route('/stocks')
def Stocks():
filename = 'stock_scraper - dev.csv'
data = pandas.read_csv(filename, header=0)
stocklist = list(data.values.flatten())
return render_template('stocks.html', stocklist=stocklist)
My web app for iterating through stocklist:
<table class="table table-striped table-sm">
<thead>
<tr>
<th>#</th>
<th>Ticker</th>
<th>Closing Price</th>
<th>Closing Date</th>
</tr>
</thead>
<tbody>
{% for eachstocks in stocklist%}
<tr>
<td>{{ eachstocks }}</td>
<td>{{ eachstocks }}</td>
<td>{{ eachstocks }}</td>
<td>{{ eachstocks }}</td>
</tr>
{% endfor %}
</tbody>
</table>
Output:
Haks, i removed the nested loop and added the list position in each value to fix it. Works now.
<tbody>
{% for value in stocklist %}
<tr>
<td>{{ value[0] }}</td>
<td>{{ value[1] }}</td>
<td>{{ value[2] }}</td>
<td>{{ value[3] }}</td>
</tr>
{% endfor %}
</tbody>
output
enter image description here
You shouldn't flatten the list.
Try this:
#app.route('/stocks')
def Stocks():
filename = 'stock_scraper - dev.csv'
data = pandas.read_csv(filename, header=0)
stocklist = list(data.values)
return render_template('stocks.html', stocklist=stocklist)
Then for the Jinja template:
<table class="table table-striped table-sm">
<thead>
<tr>
<th>#</th>
<th>Ticker</th>
<th>Closing Price</th>
<th>Closing Date</th>
</tr>
</thead>
<tbody>
{% for value in stocklist%}
<tr>
<td>{{ value[0] }}</td>
<td>{{ value[1] }}</td>
<td>{{ value[2] }}</td>
<td>{{ value[3] }}</td>
</tr>
{% endfor %}
</tbody>
</table>

How can I iterate multiple key from a dictionary in Django template

I have given data from views to template in django. I want to iterate these multiple keys to build a html table.
views.py
data={'pacientes':p,'inicios':i,'finales':f,'enfermedad':enf} # p, i and f are lists
return render(request,'verEnf.html',data)
I want to do something like
index.html
<table>
{% for p, i, f in pacientes, inicios, finales %} # I know that this code is not work
<tr>
<td>{{ p.nombre }}</td>
<td>{{ i }}</td>
<td>{{ f }}</td>
<tr>
{% endfor %}
</table>
p is an object from Pacientes
class Usuario(models.Model):
dni=models.CharField(max_length=9,primary_key=True)
clave=models.CharField(max_length=16)
nombre=models.CharField(max_length=30)
...
and i is a string's list as
('20-2-2014', '12-2-2014', ..., '11-5-2014')
I suppose that each index of paciente, inicio and finales are related between them.
Just as Ignacio says, you can write some code in the view, before passing it to the template in order to solve your problem.
A possible solution could be packing the values in a list of tuples like this:
[
(pacientes[0], inicios[0], finales[0]),
(pacientes[1], inicios[1], finales[1]),
...
]
You can achieve this easily by using the zip function in your view:
pacientes_data = zip(p, i, f)
data={'pacientes_data':pacientes_data,'enfermedad':enf} # p, i and f are lists
return render(request,'verEnf.html',data)
And in your template:
<table>
{% for p,i,f in pacientes_data %}
<tr>
<td>{{ p.nombre }}</td>
<td>{{ i }}</td>
<td>{{ f }}</td>
</tr>
{% endfor %}
</table>
Here is a working solution for similar task:
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Model Name</th>
<th scope="col">Device Count</th>
</tr>
</thead>
<tbody>
{% for all_model in all_models %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td>{{ all_model.0 }}</td>
<td>{{ all_model.1 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
In view.py
all_models = []
all_models_names = [1,2,3,4]
all_models_names_values = [1,2,3,4]
all_models = zip(all_models_names,all_models_names_values)
return render(request, "sample.html",{'all_models':all_models})

Categories