Flask-сервер, на котором запущено приложение Bokeh: как получить доступ к графикам из скрипта, сгенерированного функцией server_document ()

1

Я использовал Bokeh для построения большой базы данных и Flask для обслуживания приложения на локальном хосте. Суммированный код выглядит так:

app = Flask(__name__)

def make_doc(doc):

    def plot_time():
        p = figure(plot_height=400, plot_width=1000, tools="xpan,box_zoom,xwheel_zoom,reset,save", 
            x_axis_type="datetime", background_fill_color="#efefef",outline_line_color="#000000")       
        for us,color in zip(lista_plots,colors):
            p.line(x="Instant", y=us, source=source, name=us, line_color=color, line_width=1, legend=us.title())                
        return p

    def plot_time_aux(): 
        p = figure(plot_height=115, plot_width=1000, x_axis_type="datetime", y_axis_type=None, tools="",  background_fill_color="#efefef")
        for us in list_plots:
            p.line(x="Instant", y=us, source=source, name=us, line_color="gray", alpha=0.55)   
        return p

p1 = plot_time()
p2 = plot_time_aux()
doc.add_root(p1)
doc.add_root(p2)
doc.title = "Time Plot"

@app.route('/', methods=['GET'])

def bkapp_page():
    script = server_document('http://localhost:5006/bkapp')
    return render_template("index.html", script=script)

def bk_worker():
    server = Server({'/bkapp': make_doc}, io_loop=IOLoop(), allow_websocket_origin=["localhost:{}".format(port)])
    server.start()
    server.io_loop.start()

from threading import Thread
Thread(target=bk_worker).start()

if __name__ == '__main__':
    print('Opening single process Flask app with embedded Bokeh application on http://localhost:{}/'.format(port))
    webbrowser.open_new("http://localhost:{}/".format(port))
    app.run(port=port, debug=False) 

Код работает просто отлично, но когда дело доходит до доступа к p1 и p2 для вставки его в пользовательские элементы div в HTML-шаблоне Jinja2, я не могу понять, как это сделать. HTML-шаблон выглядит следующим образом:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Time Plots</title>
</head>
<body>
    {% for root in script.roots %}
        <div>{{ embed(root) }}</div>
    {% endfor %}
    {{ script | safe }}
</body>
</html> 

На самом деле, скрипт строит графики p1 и p2 один за другим и просто игнорирует цикл Jinja2 for (вероятно, потому что переменные, на которые я ссылаюсь в шаблоне, не существуют...). Однако я хотел бы передать каждый график (p1 и p2) в качестве аргументов в функции render_template(), чтобы я мог свободно размещать их в любом месте HTML-шаблона, но я понятия не имею, как,

Любые идеи приветствуются.

Теги:
flask
jinja2
bokeh
html-templates

1 ответ

0

Я предоставлю план того, как реализовать несколько графиков:

  1. Создайте отдельное приложение Bokeh для каждого сюжета. См. modify_doc в примере

    def change_doc1():
      # code to define how plot 1 should behave
    
    def change_doc2():
      # code to define how plot 2 should behave
    
  2. Инициализируйте сервер Bokeh несколькими приложениями вместо одного приложения

    def bk_worker():
        plots = { "/plot1": change_doc1, "/plot2": change_doc2 }
        server = Server(plots, io_loop=IOLoop(), allow_websocket_origin=["localhost:{}".format(port)])
        server.start()
        server.io_loop.start()
    
  3. Получите отдельные подсказки в маршруте Flask и отправьте их в шаблон.
    @app.route('/', methods=['GET'])
    def bkapp_page():
        script1 = server_document('http://localhost:5006/plot1')
        script2 = server_document('http://localhost:5006/plot2')
        return render_template("embed.html", script1=script1, script2=script2)
    
  4. Используйте сценарии в шаблоне отдельно и разместите его там, где вы хотите, в HTML
    <!doctype html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <title>Time Plots</title>
    </head>
    <body>
      <div id="plot1">
        {{ script1 | safe }}
      </div>
      <div id="plot2">
        {{ script2 | safe }}
      </div>
    </body>
    </html>
    
  • 0
    Эй спасибо !! Я проверю это. Моя единственная забота о наличии отдельных сценариев заключается в том, что в моем случае графики связаны между собой и обмениваются данными между ними. Как вы думаете, можно ли использовать x_range() и данные с виджетами в этой форме? Так как я задал вопрос, мне удалось получить доступ к корням в Документе Bokeh, используя bokeh serve вместо программного вызова сервера, как предлагается здесь.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню