Python 运行多页Plotly Dash应用程序,在Flask中使用回调和图形

Python 运行多页Plotly Dash应用程序,在Flask中使用回调和图形,python,flask,web-applications,plotly,plotly-dash,Python,Flask,Web Applications,Plotly,Plotly Dash,简介: 我已经有了一个多页Dash应用程序,每个页面都运行在一个单独的布局文件中,可以从主索引页面调用 什么效果好? 运行一个独立的Dash应用程序($python index.py),索引页面会显示其他条目,每个链接都可以很好地工作,并带有它们的图形和回调 ''' index.py : relevant sections ''' from appc import app, server import page1c, page2c, page3c app.layout = html.Div(

简介:


我已经有了一个多页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应用程序中使用现有Dash应用程序(
$python Flask_App.py
),但出现问题,即仅显示HTML内容(来自布局),但如果在单独的文件中定义了Dash布局,则不会触发回调

为什么?


答:计划将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)

嗨,莫尼,运气好吗?后来没试过。使用Dash保持基本站点和仪表板不变。如果在d_应用程序上切换页面输入,且目标url发生更改,flask应用程序是否会触发该url的回调?类似问题未解决此处一个有趣的替代方法是在不同端口运行应用程序,并将其1)创建代理2)嵌入应用程序:如此处所示:。我和第二个一起工作。