我用bokeh制作了一个简单的表格,如下所示:
我想为用户创建一个可下载的链接,当用户点击该按钮时,可以下载excel表。我尝试在散景表单中添加一个html标签,并将其href属性设置为服务器上Excel表格的地址。但我明白它导致了SyntaxError。
代码如下:
from bokeh.io import output_file, show
from bokeh.layouts import widgetbox
from bokeh.models.widgets import TextInput, Button, Div
from bokeh.layouts import layout, column, row
from bokeh.io import curdoc ## to assign callback to widget
from bokeh import events ## for event handling
from bokeh.models import CustomJS
import numpy as np
import pandas as pd
text_input_mean = TextInput(value="0.0", title="Enter mean:")
text_input_vaiance = TextInput(value="0.0", title="Enter variance:")
text_input_rows = TextInput(value="5", title="Enter num rows:")
text_input_columns = TextInput(value="5", title="Enter num columns:")
button = Button(label = "Generate Dataframe", button_type = "success")
text_output = TextInput(title = 'Python result is shown here: ')
div = Div(text="""Making a form with bokeh mainly to handle events.""",
width=500, height=50)
layout = column(div, row(text_input_mean, text_input_vaiance), row(text_input_rows, text_input_columns),
button, text_output)
def my_text_input_handler(attr, old, new):
print("Previous label: " + old)
print("Updated label: " + new)
text_input_mean.on_change("value", my_text_input_handler)
def button_click_handler():
text_output.__setattr__('value', str(text_input_mean.value))
text_output.value = str(text_input_mean.value)
def generate_normal_df():
mean = text_input_mean.value
variance = text_input_vaiance.value
row_num = x
col_num = y
return pd.DataFrame(np.random.normal(loc = mean, scale = variance, size=(row_num, col_num)))
button.on_click(button_click_handler)
curdoc().add_root(layout)
# this part causes error!
<html>
<b> End of page </b>
# a tag goes here
<\html>
我还没有实现如何获取生成的excel表的地址。我的想法是将数据框保存为Excel工作表;通过使用os库获取其地址,并设置标记的href属性。但是.python形式的html部分会导致错误。
能否请你提一下解决方案应该是什么?有没有办法用散景形式写html?例如,标签不可用作窗口小部件。感谢您的关注。
您可以为按钮创建纯JS回调,并将数据作为JSON下载而不涉及服务器,如下所示:
from bokeh.io import show
from bokeh.plotting import figure
from bokeh import events
from bokeh.models import CustomJS, Div, Button, RadioButtonGroup
from bokeh.layouts import column, row
import numpy as np
data = {'mean': np.arange(10), 'variance': np.random.random(10) }
button = Button(label = "Download JSON", button_type = "success")
js_download = """
var filename = 'results.json';
var blob = new Blob([JSON.stringify(data)], { type: 'text/json;charset=utf-8;' });
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename);
} else {
var link = document.createElement("a");
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
var url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link); } }"""
button.callback = CustomJS(args = dict(data = data), code = js_download)
show(button)
只需将正确的对象传递给回调即可从(例如您的数据帧)中提取数据。如果您更喜欢从服务器获取数据,那么最简单的方法是在回调中使用JS fetch()方法,就像在this example中一样。在这种情况下,您需要将代码运行为:bokeh serve --show my_app_directory
,您需要一个/static
目录,您可以在其中保存文件并将其从返回浏览器提供。或者你可以在JS回调中使用类似AjaxDataSource或纯AJAX的东西从服务器获取json并让用户下载它,如上例所示(在Bokeh v1.0.4上测试)。