我正在进行散景可视化,一个要求是它在没有服务器的情况下运行,因此我使用CustomJS
使用javascript在客户端实现交互性。将ColumnDataSource
传递给CustomJS
可以很好地交互式更新图表。
然而,我不能做的只是将一些任意json
数据嵌入到输出html中。请参阅下面的自包含示例:
from bokeh.io import output_file
from bokeh.layouts import widgetbox
from bokeh.models import CustomJS
from bokeh.models.widgets import Div, Button
from bokeh.plotting import show
data_for_client = {
"x": 3,
"y": {
"foo": [1, 2, 3],
"bar": {"some_bar": "doge", "other bar": "much json"}
},
"z": [[1, 2], [3, 4]]
}
callback = CustomJS(args={"data_for_client": data_for_client}, code="""
console.log(data_for_client);
""")
content = widgetbox(
Button(label="click here", callback=callback),
Div(text="some complicated interactive stuff based on json content here")
)
output_file("issue.html")
show(content)
就我而言,data_for_client
是一个复杂的深层嵌套json
,根据用户与某些小部件的互动,会使用此json
的不同部分。
我不需要根据用户交互对json
数据进行任何修改,也不需要附加任何听众或任何特殊内容。我只需要在CustomJS
回调中提供json值的内容。
对于简单的列数据,我可以将我的数据包装在ColumnDataSource
中并将其作为arg传递给CustomJS
,但是我找不到任何类似于普通json
数据的数据。上面的代码失败并显示消息:
ValueError: expected an element of Dict(String, Instance(Model)), got {'data_for_client': {'x': 3, 'y': {'foo': [1, 2, 3], 'bar': {'some_bar': 'doge', 'other bar': 'much json'}}, 'z': [[1, 2], [3, 4]]}}
答案 0 :(得分:1)
您需要将相关行中的第一个data_for_client
更改为"data_for_client"
,否则您无法使用字典({...})作为字典键:
from bokeh.io import output_file
from bokeh.layouts import widgetbox
from bokeh.models import CustomJS
from bokeh.models.widgets import Div, Button
from bokeh.plotting import show
data_for_client = {
"x": 3,
"y": {
"foo": [1, 2, 3],
"bar": {"some_bar": "doge", "other bar": "much json"}
},
"z": [[1, 2], [3, 4]]
}
# Here is the change:
callback = CustomJS(args={"data_for_client": data_for_client}, code="""
console.log(data_for_client);
""")
content = widgetbox(
Button(label="click here", callback=callback),
Div(text="some complicated interactive stuff based on json content here")
)
output_file("issue.html")
show(content)
答案 1 :(得分:1)
你可以把它作为字符串传递,我希望javascript中有东西从json字符串中读取json数据,我知道至少存在于python中。
from bokeh.io import show
from bokeh.layouts import widgetbox
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.models.widgets import Div, Button
import json
data_for_client = {
"x": [3],
"y": {
"foo": [1, 2, 3],
"bar": {"some_bar": "doge", "other bar": "much json"}
},
"z": [[1, 2], [3, 4]],
}
json_string = json.dumps(data_for_client)
DumButton = Button(label=json_string)
# Here is the change:
callback = CustomJS(args={"db":DumButton}, code="""
console.log(db.label);
var test=JSON.parse(db.label);
console.log(test);
for(key in test){console.log(test[key])}
""")
content = widgetbox(
Button(label="click here", callback=callback),
)
show(content)