[英]Load html table with Flask, jinja2, python and js dynamically
我使用 Flask 创建了一个测试网站,该网站显示来自 postgres 数据库的数据,按类别、产品、月份和日期排序。 每个类别下的所有表格行都被隐藏。 单击一行将展开/折叠其下方的 1 级行。 因此,单击一个类别将显示所有产品。 单击产品将显示所有月份的数据。
目前,正如您在代码中看到的,加载页面时会检索所有记录。
测试网站是显示数千条记录的网站的简化版。 我想将该网站用于具有数百万条记录的不同数据库。
不幸的是,页面加载和展开/折叠需要很长时间。 我不想在单击时折叠/展开行,而是在每次展开类别、产品或月份时使用 Flask 查询数据库,并向表中添加 1 级行,其中包含查询返回的数据。
这可以用 Flask、jinja2 和 js 来完成吗?
带有jinja2代码的html模板
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type=text/javascript src="{{url_for('static', filename='js/test.js') }}"></script>
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='styles/test.css') }}">
<title>Test Table</title>
<body>
<table class = "products">
<thead>
<tr>
<th>Product</th>
<th>Month</th>
<th>Date</th>
</tr>
</thead>
<tbody>
{% for category in types %}
<tr class="category" data-level="0" vis_id = "{{ category.category}}">
<td colspan = 3 class="nosides">
<label>{{ category.category}}</label>
</td
</tr>
{% for product in category.products %}
<tr class="parent" data-level="1" vis_id = "{{ product.product }}" par_vis_id = "{{ category.category}}">
<td colspan = 3 class="nosides">
<label>{{ product.product }}</label>
</td>
</tr>
{% for month in product.months %}
<tr class="parent" data-level="2" vis_id = "{{ product.product }}_{{ month.month }}" par_vis_id = "{{ product.product }}">
<td colspan=1 class="noright"></td>
<td colspan=2 class="nosides">
<label>{{ month.month }}</label>
</td>
</tr>
{% for date in month.date %}
<tr class="child" data-level="3" vis_id = "{{ date.date }}" par_vis_id = "{{ product.product }}_{{ month.month }}">
<td colspan = 2></td>
<td>{{ date.date }}</td>
</tr>
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}
</tbody>
</table>
</body>
</html>
Python烧瓶代码
import sys, os
from flask import Flask, render_template
import pandas as pd
import pandas.io.sql as psql
@app.route('/test_table')
def test_table():
con = set_con('db')
sys_list = []
#select all the records
df = pd.read_sql("select category, product, TO_CHAR(date, 'Mon YYYY') as month, TO_CHAR(date, 'YYYY-MM-DD HH24:MI:SS') as date \
from db order by category, product, date desc", con)
query = "Select distinct product from db order by product"
#get a list of categories, products and months, then loop over each.
df_products = pd.read_sql(query, con)
query = "Select distinct category from products"
df_sys = pd.read_sql(query,con)
for category in df_sys['category'].values:
products_list = []
df_sys_tmp = df[df['category']==category]
if df_sys_tmp.empty:
continue
for product in df_products['product'].values:
df_product_tmp = df_sys_tmp[df_sys_tmp['product']==product]
if df_product_tmp.empty:
continue
months = df_product_tmp['month'].unique()
tmp_list_months = []
for month in months:
#loop over all the records for this particular category, product, and month.
df_recs = df_product_tmp[df_product_tmp['month']==month]
if df_recs.empty:
continue
tmp_list_recs = []
for i, row in df_recs.iterrows():
tmp_list_recs.append({'date':row['date']})
tmp_list_months.append({'month':month, 'date':tmp_list_recs})
products_list.append({'product':product, 'months':tmp_list_months})
sys_list.append({'category':category, 'products':products_list})
return render_template(test.html',types=sys_list)
if __name__ == '__main__':
main()
js
function toggleIf(element, condition) {
if (condition ===true || condition === 'true') { element.show(); }
else { element.hide(); }
};
$(document).ready(function() {
function getChildren($row) {
var children = [], level = $row.attr('data-level');
while($row.next().attr('data-level') > level) {
children.push($row.next());
$row = $row.next();
};
return children.sort((a, b) => parseFloat(a.attr('data-level')) - parseFloat(b.attr('data-level')));;
};
$('.parent').on('click', function() {
var children = getChildren($(this));
var datalevel = $(this).attr('data-level')
var vis_id = $(this).attr('vis_id')
$.each(children, function() {
par_vis_id = $(this).attr('par_vis_id')
if (datalevel==1){
if ($(this).attr('data-level')==2){
$(this).toggle();}
else{
if ($(this).is(":visible")){
$(this).toggle();}}}
else{$(this).toggle();}
sessvisible = $(this).is(":visible")
if (sessvisible) {
sessionStorage.setItem(par_vis_id, 'true')
}
else{
try {
sessionStorage.removeItem(par_vis_id);}
catch { };};});
});
$('.product').on('click', function() {
var children = getChildren($(this));
var vis_id = $(this).attr('vis_id')
$.each(children, function() {
item_visible = $(this).is(":visible")
if ($(this).attr('data-level')==1){
$(this).toggle();
product_visible = $(this).is(":visible")
if (!product_visible) {
try {
sessionStorage.removeItem($(this).attr('vis_id'));}
catch { };}} else{
if (item_visible){
$(this).toggle();}
try {
sessionStorage.removeItem($(this).attr('vis_id'));}
catch { };
}})
if (product_visible) {
sessionStorage.setItem(vis_id, 'true')
}
else{
try {
sessionStorage.removeItem(vis_id);}
catch { };};
});
$('.parent').on('custom', function() {
var children = getChildren($(this));
var datalevel = $(this).attr('data-level')
var vis_id = $(this).attr('vis_id')
$.each(children, function() {
if (datalevel==1){
if ($(this).attr('data-level')==2){
$(this).toggle();}
else{
if ($(this).is(":visible")){
$(this).toggle();}}}
else{$(this).toggle();}
});
});
$('.product').on('custom', function() {
var children = getChildren($(this));
var vis_id = $(this).attr('vis_id')
$.each(children, function() {
item_visible = $(this).is(":visible")
if ($(this).attr('data-level')==1){
$(this).toggle();}
else{
if (item_visible){
$(this).toggle();}}
});
});
$('.product').each(function(i, tr) {
var isvisible = $(this).is(":visible")
var children = getChildren($(this));
var vis_id = $(this).attr('vis_id')
if (sessionStorage.getItem(vis_id) !== null){
$(this).trigger('custom');
}
$.each(children, function() {
var datalevel = $(this).attr('data-level')
if (datalevel !== '3'){
var vis_id = $(this).attr('vis_id')
if (sessionStorage.getItem(vis_id) !== null){
$(this).trigger('custom');};};
});
});
});
我能够使用 XMLHTTPRequests 和 Flask 和 JS 来做到这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.