Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] When using multiple instances of dash on a flask server, they cannot share the same page name, even though they have different url routes #2812

Open
benhutchings1 opened this issue Mar 24, 2024 · 3 comments

Comments

@benhutchings1
Copy link

benhutchings1 commented Mar 24, 2024

Library Versions

dash                 2.16.1
dash-core-components 2.0.0
dash-html-components 2.0.0
dash-table           5.0.0

Describe the bug / Expected Behaviour

See minimal test app setup below for test example

I have two dash apps (dash1, dash2) which both have a page called home. These each run on their own flask app, connected by a MiddlewareDispatcher (see test app). I expect for both these home pages to be served on /dash1/home & /dash2/home. When I try this though I get an error:

Exception: modules ['dashboards.dash1.pages.home', 'dashboards.dash2.pages.home'] have duplicate paths

When I check the page register, both dashboards have the same relative_path (see below). I believe this is because the page register is not tied to an object it is universal to all dash apps. For the full page registry, see further down.

module  dashboards.dash1.pages.home
    path            /home
    relative_path   /dash1/home <---- SAME VALUES

module  dashboards.dash2.pages.home
    path            /home
    relative_path   /dash1/home <---- SAME VALUES

If the page registry must be universal to all dash apps, I would expect the path to be prepended by url_base_pathname to avoid pathname collisions

Expected

module  dashboards.dash1.pages.home
    path            /dash1/home

module  dashboards.dash2.pages.home
    path            /dash2/home

Thank you!!

Minimal test app setup

.
├── app.py
└── dashboards
    ├── dash1
    │   ├── __init__.py
    │   └── pages
    │       └── home.py
    └── dash2
        ├── __init__.py
        └── pages
            └── home.py

app.py

from dashboards.dash1 import app as dash1
from dashboards.dash2 import app as dash2

app = Flask(__name__)

routes = {
 "/dash1": dash1.server,
 "/dash2": dash2.server
}

app.wsgi_app = DispatcherMiddleware(NotFound(), routes)

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

dash1/_init_.py

app = Dash("dash1", use_pages=True, pages_folder="dashboards/dash1/pages", url_base_pathname="/dash1/")

app.layout = html.Div([
    html.H1(children='Dash 1', style={'textAlign':'center'}),
    page_container
])

dash1/pages/home.py

register_page(__name__, name="home", path="/home")

layout = html.H1("Dash 1 Home")

dash2/_init_.py

app = Dash("dash2", use_pages=True, pages_folder="dashboards/dash2/pages", url_base_pathname="/dash2/")

app.layout = html.Div([
    html.H1(children='Dash 2', style={'textAlign':'center'}),
    page_container
])

dash2/pages/home.py

register_page(__name__, name="home", path="/home")

layout = html.H1("Dash 2 Home")

Page Register

module  dashboards.dash1.pages.home
    supplied_path   /home
    path_template   None
    path            /home
    supplied_name   home
    name            home
    supplied_title  None
    title           home
    description 
    order           None
    supplied_order  None
    supplied_layout None
    supplied_image  None
    image           None
    image_url       None
    redirect_from   None
    relative_path   /dash1/home <---- SAME VALUES
    layout          H1('Dash 1 Home')
module  dashboards.dash2.pages.home
    supplied_path   /home
    path_template   None
    path            /home
    supplied_name   home
    name            home
    supplied_title  None
    title           home
    description 
    order           None
    supplied_order  None
    supplied_layout None
    supplied_image  None
    image           None
    image_url       None
    redirect_from   None
    relative_path   /dash1/home <---- SAME VALUES
    layout          H1('Dash 2 Home')
@ned2
Copy link
Contributor

ned2 commented Mar 26, 2024

Unfortunately patterns involving running two Dash instances within the same Python process are no longer supported by Dash. This is because there's a few different bits of global state that Dash uses to track things like callbacks defined with dash.callback (as opposed to app.callback ) and, as you've bumped into, state used by the Pages feature. These have been introduced over time starting some versions of Dash ago.

Here's a post in another repo where I took a stab at identifying all the global state that you could run afoul of trying to run multiple Dash instances in the one process. if you're careful, you could get some use cases to work by avoiding features that make use of them, but in general this is going to be risky, so might be better to fall back to another way of what you're trying to achieve.

@benhutchings1
Copy link
Author

@ned2 appreciate the confirmation can stop trying to bodge it now 😆

@benhutchings1
Copy link
Author

@ned2 do you have a recommended approach to fixing this problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants