Skip to content

[BUG] PAGE_REGISTRY is global, making it impossible to have multiple dash apps with use_pages #2398

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

Closed
C0DK opened this issue Jan 25, 2023 · 3 comments

Comments

@C0DK
Copy link

C0DK commented Jan 25, 2023

Describe your context

dash                      2.7.1
dash-bootstrap-components 1.3.0
dash-core-components      2.0.0
dash-html-components      2.0.0
dash-table                5.0.0

Describe the bug
We are trying to create a flask application with multiple dash apps and utilizing use_pages. This creates a problem, however, as the PAGE_REGISTRY is a global variable:

https://github.com/plotly/dash/blob/dev/dash/_pages.py

This means that when we register multiple apps, all the apps will contain all the pages from all apps. I.e I have an app A (at URL /a/) with pages:

  • Page 1
  • Page 2

And an App B (at URL /b/) that contains:

  • Page 6
  • Page 7

Then the following routes will be registered(8 rather than the 4 actually registered):

  • /a/1/
  • /a/2/
  • /a/6/
  • /a/7/
  • /b/1/
  • /b/2/
  • /b/6/
  • /b/7/

This is not ideal.

(And ideally one probably shouldn't use global variables in your code 😛 )

Expected behavior

I expected the routes/pages to be contained within the specific dash app.

@ned2
Copy link
Contributor

ned2 commented Jan 26, 2023

what you say is spot on, that it's unsafe to run multiple Dash app instances off the same Flask server. Dash used to kinda support this (see #70), but I don't think it was truly officially supported. It actually stopped being safe to do before Dash Pages was added.

Notably, the callback decorator dash.callback, which was added back in Dash 2.0 so as not to require threading imports of your app Dash instance around your code which was prone to circular import issues, required the introduction of some global state. You can see this in dash._callback: GLOBAL_CALLBACK_LIST, GLOBAL_CALLBACK_MAP, GLOBAL_INLINE_SCRIPTS.

Oh and there's also dash.get_asset_url which similarly also relies on global state from a single Dash instance.

@alexcjohnson would be able to frame it better, but I'd say this was seen as an explicit trade-off, losing the ability to support multiple Dash instances living in the same process (which relatively few users would want) at the benefit to reducing circular import headaches, that was a friction point for pretty much everyone making Dash apps more complex than a single module.

I reckon there'd other strategies you could explore to get the workflow you're after, such as leaning into a single Dash instance that has logical "apps" sitting underneath it. The Dash Community Forum would be a better place for that discussion though.

Edit: turns out that the multi-Dash app pattern was in fact officially supported some while back, as you can see from this old snapshot of the docs. In fact... it turns out I was the original author of that content 😂

@C0DK
Copy link
Author

C0DK commented Jan 26, 2023

That's a valid point and I greatly appreciate the suggestions.

Our main hurdle is that we want different permission models on different apps l so even though we could make them
self-contained while in the same app, we might hit other hurdles then. We'll see what is possible.

Would it be feasible to make it more obvious somewhere that this is the case? I searched the web and found multiple articles with people doing exactly this, and assumed it'd be possible.

Thanks for the quick reply, never the less.

@ned2
Copy link
Contributor

ned2 commented Jan 26, 2023

Yeah totally, I reckon this should definitely be documented. Especially since, as I now remember after doing some digging, this pattern was actually supported in the Dash docs for a while.

I've created a documentation feature request over in #2399. Perhaps this issue can now be closed?

@C0DK C0DK closed this as completed Jan 30, 2023
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