0

我目前正在创建一个在服务器上运行的基于 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)
4

1 回答 1

0

这是一个错误。我刚刚创建了https://github.com/bokeh/bokeh/issues/10146

作为一种解决方法,更换

Exportbutton.js_on_click(CustomJS(args=dict(source=ColumnDataSource(df)),code = js_code  ))

Exportbutton.js_event_callbacks['button_click'] = [CustomJS(args=dict(source=ColumnDataSource(df)), code=js_code)]
于 2020-06-10T08:38:09.340 回答