使用HTTP请求控制散景图状态

时间:2016-04-13 21:57:08

标签: python bokeh

我正在创建一个散景应用程序,并希望使状态(小部件,影响图形)“可共享”。我的第一个想法是在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问题和答案是相关的,但我认为现在已经过时了散景服务器是建立在龙卷风上的。

1 个答案:

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