DispatcherMiddleware issue - Dash + Flask App integration

I am attempting to run both Flask and Dash Apps using Flask’ DispatcherMiddleware

My dash app is a multi-page Application. The structure of the App is as follows:

Deploy-Auth
- auth
  - templates
  - - base.html
  - - login.html
  - init.py
  - routes.py 
- dashapp.py
- app.py
- procfile
- requirements.txt

Contents of app.py

app = dash.Dash(__name__)

server = app.server

app.config.update({

    'routes_pathname_prefix': '',

    'requests_pathname_prefix': ''
})

Contents of dashapp.py

# App Layout
app.layout = html.Div([

    # header
    html.Div([

        
        dcc.Link(
            href=('/home'),
            children='Home',
            style={'paddingRight': 10}
        ),

        dcc.Location(id='url'),

        html.Div(id='page-content', style={'margin-left': '2%'}),

        
    )

])



# Render page content
@app.callback(Output("page-content", "children"),
              [
                Input('url', 'pathname')
              ]
             )
def display_content(pathname):

    if pathname == '/home':
        return home.layout

    elif pathname == '/archive':
        return archive.layout()

    else:
        return home.layout

Contents of routes.py

from app import app
imports .........

main = Blueprint('main', __name__)

@main.route('/')
def index():
    if not current_user.is_authenticated:
        return render_template('login.html')
    else:
        return redirect(url_for('main.profile'))

@main.route('/profile')
@login_required
def profile():
    email = current_user.email
    user = User.query.filter_by(email=email).first()
    user_obj = {'fullname':user.fullname, 'email':user.email,}
    return render_template('profile.html', user=user_obj)

Contents of init.py

from flask import Flask,redirect
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager,login_required
from app import app as dashApp

server_auth = Flask(__name__,instance_relative_config=False)

server_auth.config['SECRET_KEY'] = 'xxxxxxxxxxxx'
server_auth.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
server_auth.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# init SQLAlchemy so we can use it later in our models
db = SQLAlchemy(server_auth)

# def create_app():

db.init_app(server_auth)

login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(server_auth)

from .models import User,init_db
init_db() # created sqlite tables

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

# blueprint for auth routes in our app
from .auth import auth as auth_blueprint
server_auth.register_blueprint(auth_blueprint)

# blueprint for non-auth parts of app
from .main import main as main_blueprint
server_auth.register_blueprint(main_blueprint)

app = DispatcherMiddleware(server_auth, {
    '/dashboard': dashApp.server,
    #add dash routes
    })

if __name__ == '__main__':
    run_simple('0.0.0.0', 5000, app, use_reloader=True, use_debugger=True)

The entry points of the app, login page works. However, when I click dashboard to navigate to dashApp, I get a 404 Not Found error.

I think you want to set requests_pathname_prefix to be "/dashboard/".

Check out the example in this post.

That did not fix it. I updated the dash app initialization :


app = dash.Dash(__name__, routes_pathname_prefix='/dashboard/')

In the post you linked, all the content - initialization of flask app, dash app and dispatchmiddleware is in one place. The configuration of my app is slightly different as it is a multiple page app and the page-content is rendered using Callbacks.

The issue in my case seems to be that page-content Callback is not being triggered, when I navigate to localhost:5000/dashboard.

@tcbegley

Did you get rid of this part also? Because if not then you’re overwriting what you set with requests_pathname_prefix.

Yes, I got rid of that part.

Hmm, then it’s a bit hard to know for sure what the problem is. If you’re willing to share your code I’ll take a look and try to run it myself.

Thanks, I have shared the link to github repo in DMs.