Description
Is your feature request related to a problem? Please describe.
When hooking a Dash app into an existing Flask server, I want to configure the app's route prefix at server run time. Having to set the route prefix at Dash app initialization enforces an unnecessary coupling across app & server definitions when the route prefix could optionally be provided to init_app()
.
Right now the following hack does not work (understandably so)
import dash
import flask
# App init
app = dash.Dash(server=False)
# Server init
server = flask.Flask()
# Server run time -> configure the dash app routes dynamically
app.config.requests_pathname_prefix = '/dashboard' # <- attempting to update read-only attr
app.init_app(server)
server.run(...)
because during Dash.__init__()
certain config
kwargs like request_pathname_prefix
get set to a read only state. However, I think that this constraint doesn't need to apply to the delayed Flask init via app.init_app(server)
.
Describe the solution you'd like
The behavior that I would like is something along the lines of the following
app.init_app(server, **config_kwargs)
Where config_kwargs
is a dict (or instead a specific set of named args like request_pathname_prefix
) that update config
here.
The end result being the following structure
# app1.py
import dash
dash_app1 = dash.Dash(server=False)
# app2.py
import dash
dash_app2 = dash.Dash(server=False)
# route_config.py
from app1 import dash_app1
from app2 import dash_app2
routes = {
'/dashboard1': dash_app1,
'/dashboard2': dash_app2,
}
# main.py
import flask
from route_config import routes
server = flask.Flask('My Flask Server')
for route, dash_app in routes.items():
dash_app.init_app(server, requests_pathname_prefix=route)
server.run(host='0.0.0.0', debug=True)
The advantage to this structure is that it becomes much easier to organize url routes to Dash apps within Flask servers without forcing the Dash apps to be bound to the route that they were initialized with.
Describe alternatives you've considered
An alternative approach could look like the following
# route_config.py
routes = {
'app-id-1': '/dashboard1',
'app-id-2': '/dashboard2',
}
# app1.py
import dash
from route_config import routes
dash_app1 = dash.Dash(server=False, requests_pathname_prefix=routes['app-id-1'])
# app2.py
import dash
from route_config import routes
dash_app2 = dash.Dash(server=False, requests_pathname_prefix=routes['app-id-2'])
# main.py
import flask
from app1 import dash_app1
from app2 import dash_app2
server = flask.Flask('My Flask Server')
dash_app1.init_app(server)
dash_app2.init_app(server)
server.run(host='0.0.0.0', debug=True)
I don't think this pattern is clean as it couples Dash apps to route prefixes outside the context of the Flask server route configuration. I can think of some other alternatives to this one, but they all would enforce design patterns around Dash app inits and are not plug-and-play with any arbitrary server.
Additional context
I think the proposed behavior makes it simple to define Dash apps independent of their server's route configuration. In my use case, I am working on a second Flask server that is using some of the same Dash apps as the first Flask server. But because the Dash apps are bound to their route configs at init, they are forced to have the same route config across all Flask servers as opposed to letting each Flask server configure it's own routes.
Closing Thoughts
I've been a Dash power user for several years and it's an excellent product - thank you for the time you put into making this robust.
I think this change is viable based on a review of the Dash __init__()
and init_app()
methods. I'm happy to take a crack at a PR for this, but I would prefer some feedback/review of this idea before I start hammering away. Thanks! :)