python - 在 Flask 中运行带有回调和图表的多页 Plotly-Dash 应用程序
问题描述
介绍:
我已经有一个多页 Dash 应用程序,每个页面都运行到一个单独的布局文件中,并且可以从主索引页面调用。
什么效果好?
运行独立的 Dash 应用程序 ( $python index.py
),索引页面与其他条目一起显示,每个链接都运行良好,带有它们的图表和回调。
'''
index.py : relevant sections
'''
from appc import app, server
import page1c, page2c, page3c
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-content')
])
...
...
..
index_page = html.Div([ ....
# Similar to calling in flask_app.py
------------------------------------------------------------
'''
appc.py : relevant sections
'''
app = dash.Dash('auth')
auth = dash_auth.BasicAuth(
app,
VALID_USERNAME_PASSWORD_PAIRS
)
server = app.server
app.config.suppress_callback_exceptions = True
...
..
'''
什么不好?
答:尝试在 Flask 应用程序 ( $python flask_app.py
) 中使用现有的 Dash 应用程序,但如果在单独的文件中定义 Dash 布局,则会出现仅 HTML 内容(显示布局)但不会触发回调的问题。
为什么?
答:计划将 Flask 用于主要网站和功能,将 Dash 用于交互式图形和 HTML 布局。
尝试的解决方案:
下面是来自 flask_app.py 的代码,我已经评论了我的最佳能力。
'''
flask_app.py : Attempt to run dash and flask based routes in one instance.
'''
from flask import Flask, render_template
from dash import Dash
from dash.dependencies import Input, State, Output
import dash_core_components as dcc
import dash_html_components as html
import json
import plotly
import pandas as pd
import numpy as np
server = Flask(__name__)
########################################################################
@server.route('/graph') # Interactive Dash Graph in predefined HTML
def index():
rng = pd.date_range('1/1/2011', periods=7500, freq='H')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
graphs = [
dict(
data=[
dict(
x=[1, 2, 3],
y=[10, 20, 30],
type='scatter'
),
],
layout=dict(
title='first graph'
)
),
dict(
data=[
dict(
x=[1, 3, 5],
y=[10, 50, 30],
type='bar'
),
],
layout=dict(
title='second graph'
)
),
dict(
data=[
dict(
x=ts.index, # Can use the pandas data structures directly
y=ts
)
]
)
]
# Add "ids" to each of the graphs to pass up to the client
# for templating
ids = ['Graph-{}'.format(i) for i, _ in enumerate(graphs)]
# Convert the figures to JSON
# PlotlyJSONEncoder appropriately converts pandas, datetime, etc
# objects to their JSON equivalents
graphJSON = json.dumps(graphs, cls=plotly.utils.PlotlyJSONEncoder)
return render_template('layouts/graph.html',
ids=ids,
graphJSON=graphJSON)
########################################################################
@server.route('/hello') # Static predefined HTML
def hello_index():
return render_template('hello.html',)
########################################################################
app = Dash(server=server, url_base_pathname='/dash') # Interactive Dash input box with callback.
app.layout = html.Div([
html.Div(id='target'),
dcc.Input(id='input', type='text', value=''),
html.Button(id='submit', n_clicks=0, children='Save')
])
@app.callback(Output('target', 'children'), [Input('submit', 'n_clicks')],
[State('input', 'value')])
def callback(n_clicks, state):
return "callback received value: {}".format(state)
######################################################################
app = Dash(__name__, server=server, url_base_pathname='/dashed') #Another Bash Graph inline, no callbacks.
app.layout = html.Div(children=[
html.Div(children='''
Dash: A web application framework for Python
'''),
dcc.Graph(
id='example-graph',
figure={
'data': [
{'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
{'x': [1, 2, 3], 'y': [2, 4, 6], 'type': 'bar', 'name': 'Montreal'},
],
'layout': {
'title': 'Dash Data Visualization'
}
}
)
])
########################################################################
'''
Content from 'index.py' : Check above.
page1c, page2c, page3c are dash separate layout files for a multipage website with dash, which is working perfect.
These are called in 'index.py' (main page) respectively as below.
Running 'python index.py' (standalone dash instance), all the interactive pages are responsive and plot the data (with callbacks) they're intended to.
But running with flask, pages only show HTML content, sliders and dropdown boxes, but the backend processes aren't triggering so no graphs are generated.
'''
# Note: 'index_page' is the layout with 3 links to above items.
# All 3 files have multiple layout (with graphs and callbacks), different files for everyone to keep it simple and less cluttered.
import page1c, page2c, page3c
from index import index_page
d_app = Dash(server=server, url_base_pathname='/', )
d_app.layout = html.Div([
html.Div(id='page-content'),
dcc.Location(id='url', refresh=True),
])
@d_app.callback(Output('page-content', 'children'),
[Input('url', 'pathname')])
def display_page(pathname):
if pathname == '/page1':
return page1c.layout
elif pathname == '/page2':
return page2c.layout
elif pathname == '/page3':
return page3c.layout
else:
return index_page
######################################################################
if __name__ == '__main__':
app.run_server(port=9999, debug=True)
解决方案
推荐阅读
- unity3d - 团结 | 场景重新加载时的 MissingReferenceException
- optimization - 在一些非改进的迭代之后如何阻止 GLPK 破坏和切割
- r - 比较不同列表中嵌入数据框的特定列
- node.js - 在 docker 容器中运行 JEST 时找不到 Jest
- flutter - Flutter / Dart 语法高亮不工作
- python - DISCORD.PY 用于循环通道 ID 清除
- python - Selenium - 即使在验证后也无法找到元素
- javascript - React Admin - 如何禁用验证 onChange
- javascript - Javascript手风琴在新标签打开时崩溃
- java - Java - WatchService 在使用 linux cp 时选择 [有时] 文件为空