Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integrating Dash apps into Flask: minimal example

I want to create a Flask web-application. I want to integrate several Dash-Apps into this site and display links to each Dash-app on the home page. Here is a minimal example: The home page should look like this:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def main():
   return "Hello World"

if __name__ == "__main__":
   app.run(debug = True)

Lets say we have a Dash app that looks like this:

import dash
import dash_html_components as html 
app = dash.Dash(__name__)

app.layout = html.Div("Hello world 1")

if __name__=="__main__":
    app.run_server(debug=True)

My question is now: How can I integrate the Dash app into the Flask app in the following way: 1) there should be a link in the Flask-app leading to the Dash app 2) the location of the Dash app should be for example /dash (the home page is in that case located at/) 3) if there is a second and third Dash-app, it should be easy to add another link and location (e.g. /dash2, /dash3,...)

There are many posts dealing with this issue - however, I found no minimal example.

like image 206
ehi Avatar asked Jan 07 '20 11:01

ehi


2 Answers

Looks like few things have changed and needs to be updated in both Combining One or More Dash Apps with Existing WSGI Apps and Multiple Dash app without WSGI.

  1. DispatcherMiddleware now needs to be imported from werkzeug.middleware.dispatcher rather than werkzeug.wsgi in run.py / wsgi.py, as appropriately.
  2. Also, the flask_app needs to be imported appropriately.
like image 125
Balepur Avatar answered Nov 16 '22 08:11

Balepur


Combining One or More Dash Apps with Existing WSGI Apps

The following example illustrates this approach by combining two Dash apps with a Flask app.

flask_app.py

from flask import Flask

flask_app = Flask(__name__)

@flask_app.route('/')
def index():
    return 'Hello Flask app'

app1.py

import dash
import dash_html_components as html

app = dash.Dash(
    __name__,
    requests_pathname_prefix='/app1/'
)

app.layout = html.Div("Dash app 1")  

app2.py

import dash
import dash_html_components as html

app = dash.Dash(
    __name__,
    requests_pathname_prefix='/app2/'
)

app.layout = html.Div("Dash app 2") 

wsgi.py

from werkzeug.wsgi import DispatcherMiddleware

from app1 import app as app1
from app2 import app as app2

application = DispatcherMiddleware(flask_app, {
    '/app1': app1.server,
    '/app2': app2.server,
})  

In this example, the Flask app has been mounted at / and the two Dash apps have been mounted at /app1 and /app2. In this approach, we do not pass in a Flask server to the Dash apps, but let them create their own, which the DispatcherMiddleware routes requests to based on the prefix of the incoming requests. Within each Dash app, requests_pathname_prefix must be specified as the app's mount point, in order to match the route prefix set by the DispatcherMiddleware.

Note that the application object in wsgi.py is of type werkzeug.wsgi.DispatcherMiddleware, which does not have a run method. This can be run as a WSGI app like so:

$ gunicorn wsgi:application 

Alternatively, you can use the Werkzeug development server (which is not suitable for production) to run the app:

run.py

from werkzeug.wsgi import DispatcherMiddleware
from werkzeug.serving import run_simple

from app1 import app as app1
from app2 import app as app2

application = DispatcherMiddleware(flask_app, {
    '/app1': app1.server,
    '/app2': app2.server,
})

if __name__ == '__main__':
    run_simple('localhost', 8050, application) 

If you need access to the Dash development tools when using this approach (whether running with a WSGI server, or using the Werkzeug development server) you must invoke them manually for each Dash app. The following lines can be added before the initialisation of the DispatcherMiddleware to do this:

app1.enable_dev_tools(debug=True)
app2.enable_dev_tools(debug=True)  

Note: debug mode should not be enabled in production. When using debug mode with Gunicorn, the --reload command line flag is required for hot reloading to work.

In this example, the existing app being combined with two Dash apps is a Flask app, however this approach enables the combination of any web application implementing the WSGI specification. A list of WSGI web frameworks can be found in the WSGI documentation with one or more Dash apps.

Reference - https://dash.plot.ly/integrating-dash

Edited:

Multiple Dash app without WSGI

from dash import Dash
from werkzeug.wsgi import DispatcherMiddleware
import flask
from werkzeug.serving import run_simple
import dash_html_components as html

server = flask.Flask(__name__)
dash_app1 = Dash(__name__, server = server, url_base_pathname='/dashboard/')
dash_app2 = Dash(__name__, server = server, url_base_pathname='/reports/')
dash_app1.layout = html.Div([html.H1('Hi there, I am Dash1')])
dash_app2.layout = html.Div([html.H1('Hi there, I am Dash2')])
@server.route('/')
@server.route('/hello')
def hello():
    return 'hello world!'

@server.route('/dashboard/')
def render_dashboard():
    return flask.redirect('/dash1')


@server.route('/reports/')
def render_reports():
    return flask.redirect('/dash2')

app = DispatcherMiddleware(server, {
    '/dash1': dash_app1.server,
    '/dash2': dash_app2.server
})

run_simple('0.0.0.0', 8080, app, use_reloader=True, use_debugger=True)
like image 13
Chetan Patel Avatar answered Nov 16 '22 09:11

Chetan Patel