✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
⚡️ Concerned about the grid? Kyle Baranko teaches how to predicting peak loads using XGBoost. Register for the August webinar!

Serve layout after Flask routing

Hello everyone,
let me try to explain what is my issue in simple words and if it’s really solvable or not in a different way I already did but it doesn’t convince much.
Because this is not a personal project, I will not share the exact code I am using but I think we will make an idea with some adjustments.
I have a Plotly Dash application embedded into a Flask application with following routes:

# This includes all the login for performing authorisation flow with an identity provider

@app.before_request
def protect_views(): 
    # Protect all the views

@app.route(LOGIN_URL_PATH)
def login():
    # Login

@app.route(LOGOUT_URL_PATH)
def logout():
   # Logout

The app.py entrypoint is roughly the following:

# Startup and run the Flask server attached with some configuration

app = Dash(__name__, server=Flask(), suppress_callback_exceptions=True). # using a flask server

app.layout = serve_layout
callbacks.register_callbacks(app)

if __name__ == "__main__":
    app.run_server(debug=True, host="0.0.0.0", port=5000)

as you can see, I use two functions: serve_layout for serving the layout I prepared into into a layout.py file and register_callbacks for registering my callbacks into a callbacks.py file. Specifically, my layout.py looks like this:

def serve_layout():
    result = get_data_from_database()     # Pseudocode, getting data from a DB 
    input_data = result.to_dict("records")
    table = pac.DataTable(
        id='dash_table',
        data=input_data,
        columns=prepare_columns(input_data),
        editable=True,
        filter_action="native",
        sort_action="native",
        sort_mode="multi",
        column_selectable="multi",
        row_selectable="multi",
        page_action="native",
        page_current=0,
        page_size=10,
        style_table={'overflowY': 'scroll'},
    )

    out = html.Div(id='output', style={'display': 'none'})

    layout = html.Div(children=[
        html.H4(id='page-id', children=["Hello"], style={'text-align': 'right'}),
        html.Div(id="page-content",children=[html.Div(children=[table]), out])
        ]
    )
    return layout

So, I am able to run the server but when it comes to get_data_from_database() my code fails because I have a dependency from my authorisation flow: in other words, I have to perform my authorisation flow first, get a token that I need to provide to my function in order to establish a connection, retrieve the data and visualise them. Even if I am not providing the full code, my question is clear: is it possible to do something like this? I actually was able to solve it by authenticating first and performing my query afterwards if I included my table rendering in a callback, in order to render it after I have a Flask session available and I included all the pieces in my application context. It means, like this:

    @dashapp.callback(
        Output('page-content', 'children'),
        Input("output", "children"),
    )
    def display_table(children):
         result = get_data_from_database()     # Pseudocode, getting data from a DB 
        return pac.DataTable(
            id='dash_table',
            data=input_data,
            columns=prepare_columns(input_data),
            editable=True,
            filter_action="native",
            sort_action="native",
            sort_mode="multi",
            column_selectable="multi",
            row_selectable="multi",
            page_action="native",
            page_current=0,
            page_size=10,
            style_table={'overflowY': 'scroll'},
        )

But, this solution doesn’t convince me because of two reasons:

  • I want to achieve something different. The use of serve_layout helped me a bit because it enables dynamic layout, when I run the server and try to access my application locally, it tries to build my layout first other than start the routing. I found a few similar examples but not exact as I need. I know and understand how Plotly Dash applications work but I was wondering if there’s some kind of workaround to do it or a nicer solution.
  • The proposed solutions is extremely slow

I hope that someone can give me some insights? Maybe aslo something I didn’t understand properly. Thanks