我目前正在创建一个在服务器上运行的基于 Python- Bokeh的 webapp 应用程序。在此应用程序中,用户可以预览来自 pandas 数据框的数据(使用 BOKEH DATATABLE 显示),并可以根据业务需要修改数据。刷新数据框后,用户需要通过单击 BOKEH BUTTON 小部件将数据框导出到他的本地系统(以 csv 格式) 。
现在我能够创建 webapp 应用程序,但是在将数据导出到本地系统时会导致问题。当我单击按钮下载时,会下载一个 csv 文件,其中包含数据框中的初始默认数据。之后,即使我更新了数据框并再次单击“下载”按钮,也会下载相同的旧默认数据,而不是更新的数据框。
下面是我最后尝试的代码。请建议,需要对以下代码段进行哪些更改,以便每次刷新数据并单击下载按钮时,它将导出数据表中显示的最新数据。
from bokeh.io import curdoc
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.models.widgets import DataTable, NumberFormatter, TableColumn, Button
from bokeh.layouts import column,row
import pandas as pd
import numpy as np
# Create Default data
data = {'COL_1_DEFAULT': np.random.randint(200, size=100),
'COL_2_DEFAULT': np.random.randint(200, size=100),
'COL_3_DEFAULT': np.random.randint(200, size=100),
'COL_4_DEFAULT': np.random.randint(200, size=100)}
TABLE1_DATA = pd.DataFrame(data)
source_new = ColumnDataSource(TABLE1_DATA)
Columns_tab1 = [TableColumn(field=Ci, title=Ci) for Ci in TABLE1_DATA.columns] # bokeh columns
data_table1 = DataTable(columns=Columns_tab1, source=source_new,height = 200)
# Javascript for exporting data
js_code="""
var data = source.data;
var columns = Object.keys(source.data);
var filetext = [columns.join(',')].shift().concat('\\n');
var nrows = source.get_length();
for (let i=0; i < nrows; i++) {
let currRow = [];
for (let j = 0; j < columns.length; j++) {
var column = columns[j]
currRow.push(source.data[column][i].toString())
}
currRow = currRow.concat('\\n')
var joined = currRow.join();
filetext = filetext.concat(joined);
}
var filename = 'data_output.csv';
var blob = new Blob([filetext], { type: 'text/csv;charset=utf-8;' });
//addresses IE
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, filename);
}
else {
var link = document.createElement("a");
link = document.createElement('a')
link.href = URL.createObjectURL(blob);
link.download = filename
link.target = "_blank";
link.style.visibility = 'hidden';
link.click();
URL.revokeObjectURL(link.href);
}
"""
# Created Button for Export
Exportbutton = Button(label="Download", button_type="success")
Exportbutton.js_on_click(CustomJS(args=dict(source=source_new),code = js_code ))
def refresh_table():
global source_new,Columns_tab1,data_table1,button
global TABLE1_DATA
df = []
for ii in range(1, 11):
df.append({'x': ii,
'y': 1000 * np.random.rand(),
'z' : 11 * np.random.rand()
})
df = pd.DataFrame(df)
source_new = ColumnDataSource(df)
Columns_tab1 = [TableColumn(field='x', title='Col 1'),TableColumn(field='y', title='Col 2',formatter=NumberFormatter(format='$0,0.00',text_align='right')),TableColumn(field='z', title='Col 3')]
data_table1.update(source=source_new, columns=Columns_tab1, width=500, height=200)
Exportbutton.js_on_click(CustomJS(args=dict(source=ColumnDataSource(df)),code = js_code ))
# Created Button for Refreshing dataframe data
table_Refresh_Button = Button(label='Refresh Table',height = 30,width = 200,button_type="success")
table_Refresh_Button.on_click(refresh_table)
layout = column(data_table1,table_Refresh_Button, Exportbutton)
curdoc().add_root(layout)