Dash - 'Error loading layout'


#1

Hi there, I am trying to run a dash app instance on pythonanywhere.com with my main flask app.

When I run the sample code from dash tutorial

import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash()

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),

    html.Div(children='''
        Dash: A web application framework for Python.
    '''),

    dcc.Graph(
        id='example-graph',
        figure={
            'data': [
                {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
                {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
            ],
            'layout': {
                'title': 'Dash Data Visualization'
            }
        }
    )
])

if __name__ == '__main__':
    app.run_server(debug=True)

I get an error displayed on my browser ‘Error loading layout’

WSGI

import sys
project_home = u'**********'
if project_home not in sys.path:
    sys.path = [project_home] + sys.path

from werkzeug.wsgi import DispatcherMiddleware
from flask_app import server as app1
from dash_app import app as app2

application = DispatcherMiddleware(app1, {
    '/dash':    app2.server
})

I haven’t been able to find any threads related to this specific error. Any help/comment is welcomed!


#2

See Dash - pythonanywhere deployment issue


#3

Thanks for your reply.

Actually I have seen that thread and followed what you suggested before this. I don’t see any errors on my server log too.


#4

Perhaps start by seeing if the problem is associated with a minimal version that just sets application to your Dash app.server.

Another suggestion, try app = dash.Dash(__name__). The name param (which we’re setting to the current module here) will be passed onto the Flask server that is created. Sometimes this doesn’t matter, but sometimes this is important for Flask.


#5

Thank you for your reply.

I managed to find a similar solution that worked for me here

I think the issue is with DispatcherMiddleWare. Though I am not quite sure why the suggested structure here (http://flask.pocoo.org/docs/0.12/patterns/appdispatch/#combining-applications) wouldn’t work for flask and dash.


#6

After playing around I worked out what the problem is (then discovered someone else already had worked it out too).

The issue is that when you mount the Dash app at /dash, while the dispatcher is aware of this prefix, the Dash app itself is not. In particular the API requests from the client are still being directed to their various endpoints at the root. For example the failed request that leads to the error you see is going to /_dash-layout, when it should be going to /dash/_dash-layout. As suggested in the post I linked to, you can fix this by updating Dash’s request route prefix to make it relative rather than absolute, like this:

app.config.requests_pathname_prefix = ''

This however will break if you provide a custom value of url_base_pathname when creating a Dash instance. I think a more general solution could be this, however I haven’t tested it all that thoroughly:

app.config.requests_pathname_prefix = app.config.routes_pathname_prefix.split('/')[-1]

Also, I think the reason that Stackoverflow answer you linked to works, is not because it solves this problem, but because it just works around it by having the Dash app’s Flask instance be mounted at the root and therefore does not have to worry about the discrepancy between prefixes. The approach I’ve suggested, is more general, allowing you to mount the Dash instance wherever you want.


#7

@chriddyp, I wonder, do you think that could be a potentially more robust default value for requests_pathname_prefix within the Dash class?