如何使用`CustomJS`将任意`json`数据从python传递到bokeh

时间:2017-10-30 17:37:39

标签: python bokeh

我正在进行散景可视化,一个要求是它在没有服务器的情况下运行,因此我使用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]]}}

2 个答案:

答案 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)