Serving layouts on application startup conflicting with request context requirements

I’m attempting to serve a layout that dynamically changes based on the login information from a user. The serve layout function looks something like this:

def create_layout(server, url):

    app = Dash(
        __name__, 
        server=server, 
        url_base_pathname=url, 
        external_stylesheets=[dbc.themes.BOOTSTRAP], 
        suppress_callback_exceptions=True, 
        long_callback_manager=long_callback_manager
    )

    with server.app_context():
        register_callbacks(app)

        def serve_layout():

            return html.Div(
                id = 'all',
                className = 'all',
                children = [
                    html.Div(
                        id = 'content',
                        children = dynamic_layout(session.get('user'))
                    )
                ]
            )

        app.layout = serve_layout

And the app is created in a block like this

def create_app():
    """
    Create DASH web app with same instance as flask server
    """
    server = Flask(__name__) 
    server.config['SECRET_KEY'] = 'the_most_secret_key'

    create_layout(server, r'/coolapp/')

    server.register_blueprint(login)

    return server

server = create_app()

if __name__ == '__main__':
    port = 8080
    host = '0.0.0.0'
    server.run(host=host, port=port)

Im using flask as the server and this dash app is only one endpoint on a many page web application. The problem I am encountering is that the session method requires a request context in order to be used, but upon attempting to load the application, instead of waiting for the /coolapp/ url to be requested, the create_app function is fired upon server initialization and a ‘Working outside of request context’ error is thrown.

Do I have to completely scrape this strategy of passing through session information from stored cookies? I wanted to keep variable info out of the URL, so it seems like I may just be missing something simple here in getting this method to work.

Thanks

Hello @bparzonz,

What you can do is have an if clause for the layout. If there is no request, just return a blank div, otherwise return your layout.

When the app inits, it goes through and verified the layouts and tests for issues so that you can fix them. Thus, it has no request.

Thanks for the reply.

Does this involve creating a flask route? Or is there some simpler way of checking if a request has been submitted on initialization?

What I’m thinking is the default would be some blank div, but then I’d create a get post using flask on the same url path that returns what I want.

def create_layout(server, url):

    app = Dash(
        __name__, 
        server=server, 
        url_base_pathname=url, 
        external_stylesheets=[dbc.themes.BOOTSTRAP], 
        suppress_callback_exceptions=True, 
        long_callback_manager=long_callback_manager
    )

    with server.app_context():
        register_callbacks(app)

        def serve_layout():
            if not flask.request:
                return html.Div()
            return html.Div(
                id = 'all',
                className = 'all',
                children = [
                    html.Div(
                        id = 'content',
                        children = dynamic_layout(session.get('user'))
                    )
                ]
            )

        app.layout = serve_layout

Something like this should work.

Worked fabulously. Thankyou!

1 Like