我正在创建一个散景应用程序,并希望使状态(小部件,影响图形)“可共享”。我的第一个想法是在URL中使用查询字符串。但是,我不确定应用程序是否可以使用实际的HTTP请求。
一个例子:
# main.py
from bokeh.models.widgets import Select
from bokeh.plotting import Figure
from bokeh.io import curdoc, vform
p = Figure()
selector = Select(title="Select", options=["1", "2", "3"], value="2")
p.line([1, selector.value], [1, selector.value])
curdoc().add_root(vform(p, selector))
与bokeh serve main.py
一起提供,并在http://localhost:5006/main
访问。
如果我导航到http://localhost:5006/main?select=3
,是否有办法让应用程序知道原始请求包含select=3
并且在图中反映的最多为3而不是默认值为2?或者我是以完全错误的方式接近这个,并错过了更好的解决方案?
This问题和答案是相关的,但我认为现在已经过时了散景服务器是建立在龙卷风上的。
答案 0 :(得分:0)
最终我能够让这个工作。我不确定我是否真的建议任何人使用此代码,但万一它有用....
我将Bokeh应用程序包装在Flask应用程序中。基本思想是在烧瓶视图中解析查询参数,然后遍历Bokeh文档,根据查询参数更新对象。
我更新了main.py
以包含state
,这是一个可由查询参数控制的小部件列表
# file: main.py
# ...
state = [selector]
# ...
我们在app.py
,Flask(或Django /无论)应用中导入它。
# file: app.py
import json
from urllib.parse import urlencode
from flask import Flask, request, render_template
from bokeh.client import pull_session
from bokeh.embed import autoload_server
app = Flask(__name__)
@app.route('/')
def index():
session = pull_session(app_path='/main')
doc = session.document
update_document(doc, request) # this is the important part
script = autoload_server(model=None,
app_path='/main', session_id=session.id)
return render_template('index.html', script=script, session_id=session.id)
def update_document(doc, request):
'''
Update a Bokeh document according to the query string in ``request``
Parameters
----------
doc: Bokeh.Document
request: flask.request
Returns
-------
None: (Modifies doc inplace)
'''
for k, v in request.args.items():
# titles must be unique
model = doc.select_one(dict(title=k))
v = parse_query_value(v)
model.update(value=v)
def parse_query_value(v):
'''
Parse a single parameter's value from the query string
Parameters
----------
v : str
Returns
-------
parsed : object
'''
if v.startswith('['):
return json.loads(v.replace("'", '"'))
return v
@app.route('/state/<session_id>')
def get_state(session_id):
'''
Get the current widget state.
Parameters
----------
session_id : int
id of the connection to the bokeh server from ``session.id``.
this should be unique per tab.
'''
session = pull_session(app_path='/main',
session_id=session_id)
doc = session.document
params = {}
for key in state:
params[key] = doc.select_one(dict(title=key)).value
return urlencode(params)
if __name__ == '__main__':
app.run()
index.html
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 class='title'>Title</h1>
<div class="plot">{{ script|safe }}</div>
</body>
</html>