Create a multipage dash app with an existing Flask install

Following the instructions here for passing a Flask server to a Dash app, I am trying to set up a multipage app as described here.

My Flask app and the separate dash scripts are

Flask starting page

import sys, os
import dash
from flask import Flask
from dash import Dash, dcc, html

server = Flask(__name__)
server.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0

def test_app():
    return app.index()

app = Dash(__name__, server = server, requests_pathname_prefix='/myapp/', use_pages=True)

app.layout = html.Div([
	html.H1('Multi-page app with Dash Pages'),

                    f"{page['name']} - {page['path']}", href=page["relative_path"]
            for page in dash.page_registry.values()


if __name__ == '__main__':


import dash
from dash import html, dcc

dash.register_page(__name__, relative_path="/myapp/")

layout = html.Div(children=[
    html.H1(children='This is our Archive page'),

        This is our Archive page content.


I am getting the errors below:

[Tue Mar 07 09:31:00.494813 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote] mod_wsgi (pid=1744228): Failed to exec Python script file '/var/www/wsgi-scripts/myapp.wsgi'.
[Tue Mar 07 09:31:00.494865 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote] mod_wsgi (pid=1744228): Exception occurred processing WSGI script '/var/www/wsgi-scripts/myapp.wsgi'.
[Tue Mar 07 09:31:00.495206 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote] Traceback (most recent call last):
[Tue Mar 07 09:31:00.495255 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]   File "/var/www/wsgi-scripts/myapp.wsgi", line 4, in <module>
[Tue Mar 07 09:31:00.495264 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]     from hello import app as application
[Tue Mar 07 09:31:00.495273 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]   File "/var/www/wsgi-scripts/", line 14, in <module>
[Tue Mar 07 09:31:00.495279 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]     app = Dash(__name__, server = server, requests_pathname_prefix='/myapp/', use_pages=True)
[Tue Mar 07 09:31:00.495288 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]   File "/opt/miniconda3/envs/py38/lib/python3.8/site-packages/dash/", line 494, in __init__
[Tue Mar 07 09:31:00.495294 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]     self.init_app()
[Tue Mar 07 09:31:00.495303 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]   File "/opt/miniconda3/envs/py38/lib/python3.8/site-packages/dash/", line 578, in init_app
[Tue Mar 07 09:31:00.495314 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]     self.enable_pages()
[Tue Mar 07 09:31:00.495323 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]   File "/opt/miniconda3/envs/py38/lib/python3.8/site-packages/dash/", line 2045, in enable_pages
[Tue Mar 07 09:31:00.495329 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]     self._import_layouts_from_pages()
[Tue Mar 07 09:31:00.495338 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]   File "/opt/miniconda3/envs/py38/lib/python3.8/site-packages/dash/", line 2017, in _import_layouts_from_pages
[Tue Mar 07 09:31:00.495344 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]     spec.loader.exec_module(page_module)
[Tue Mar 07 09:31:00.495353 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]   File "/var/www/wsgi-scripts/pages/", line 4, in <module>
[Tue Mar 07 09:31:00.495359 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]     dash.register_page(__name__, relative_path="/myapp/")
[Tue Mar 07 09:31:00.495368 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]   File "/opt/miniconda3/envs/py38/lib/python3.8/site-packages/dash/", line 275, in register_page
[Tue Mar 07 09:31:00.495374 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote]     if context_value.get().get("ignore_register_page"):
[Tue Mar 07 09:31:00.495391 2023] [wsgi:error] [pid 1744228:tid 140322294171392] [remote] LookupError: <ContextVar name='callback_context' at 0x7f9f34aca9a0>

I have modified the code as suggested and still receive the same error.

I have found very little about the cause of LookupError: <ContextVar name=‘callback_context’ or /site-packages/dash/", line 275, in register_page

Also, I was able pass a Flask server to a dash app when not using register_page and seperate files.

My initial thought is I have the wrong relative_path, requests_pathname_prefix, url_base_pathname and requests_pathname_prefix options. Trying different permutations of them hasn’t worked yet.

Hello @jgm,

Typically, I keep app as the Dash app and then server as the Flask server.

Also, note that typically the routing for the server needs to go above the initialization of the Dash app. I also dont know if you can just have the ‘/’ redirect to a flask page, but you are welcome to give it a shot.

1 Like

Hello @jgm,

I dont think that I would label this as multipage, its like a mash of flask routing used to create an index file.

For me, I have my existing flask server have all the routings, just like I am assuming you have, and then just register the pages in the dash app.

Flask routing takes priority over Dash routing, so you dont have to worry about stepping on toes until you are all ready to swap pages, or if you ever want to.

I have deleted my answer because I wasn’t able to apply it to a more complex app.

1 Like

Using your example, this works for me:

from dash import Dash, dcc, html, Input, Output, page_container
from pages import app1, app2
from server import server
from flask import Flask

app = Dash(name, server=server, suppress_callback_exceptions=True,requests_pathname_prefix='/myapp/')

app.layout = html.Div(page_container)

if __name__ == '__main__':

Then in your pages files, register the page as where they are supposed to be in the url space. Making sure there isnt a Flask routing there.

Let your Flask server handle the error pages. Or, if you have a load balancer, you can just redirect those messages to a specific page.

Thanks Jinnyzon. FYI, I’m trying to deploy an app to a server running mod_wsgi, Apache and Flask.

I add the line below to a .conf file.
WSGIScriptAlias /myapp /var/www/wsgi-scripts/myapp.wsgi

And create the myapp.wsgi file like this

import sys
sys.path.insert(0, ‘/var/www/wsgi-scripts’)
from flask_app import server as application

I then use a mashup, as you stated, to call app.index() from the flask app I imported to the myapp.wsgi file.

Maybe I need to step back and ask, how do I deploy a Dash app to a mod_wsgi Apache and Flask setup other than calling app.index() from within the Flask app.

Would I just add another WSGISCriptAlias and create a new wsgi file that imports the Dash App?

Once I can deploy a single Dash app without resorting to calling app.index(), then I can figure out how to deploy multiple apps.

So, another thing I will say, when running the app from something like gunicorn. You run the dash app’s server, so you dont need to run them separately.

So, if you have Flask already working in that setup, replace the Flask app with the Dash app’s server, and you should get the same result that you are after.

Thanks jinnyzor. Adding new a WSGIScriptAlias and wsgi file for each dash app and replacing the flash server with the dash app.server gave me the desired functionality.