Multi-page feature update callbacks and layout based on the route path

I am trying to use Dash multi-page feature for my project. But it seems like it will load all pages’ layouts during initialization. I found a way to prevent updating as following code.

Is there any better way to do this? Although it can work, it has other callbacks and components in page_2, it will throw errors for page_2 when accessing page_1.

dash_app.py

import dash
from dash import Dash, html, dcc

app = Dash(__name__, use_pages=True)

app.layout = html.Div([
    dcc.Location(id='url', refresh='callback-nav' ),
    html.Div(id='page-content'),
    dash.page_container
])

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

pages/page_1.py

import dash
from dash import html, callback
from dash.dependencies import Output, Input
from dash.exceptions import PreventUpdate

dash.register_page(__name__)

def layout():
    print('page_1 init')
    return

def page_1_layout():
    print('page_1 layout init')
    return html.Div(children=[
        html.H1(children='page_1'),
        html.Div(children='''
            This is page_1.
        '''),
    ])

@callback(
    Output('page-content', 'children', allow_duplicate=True),
    Input('url', 'pathname'),
    prevent_initial_call='initial_duplicate'
)
def update_page(path):
    if path == '/page_1':
        return page_1_layout()
    else:
        raise PreventUpdate

pages/page_2.py

import dash
from dash import html, callback
from dash.dependencies import Output, Input
from dash.exceptions import PreventUpdate

dash.register_page(__name__)

def layout():
    print('page_2 init')
    return

def page_2_layout():
    print('page_2 layout init')
    return html.Div(children=[
        html.H1(children='page_2'),
        html.Div(children='''
            This is page_2.
        '''),
    ])

@callback(
    Output('page-content', 'children'),
    Input('url', 'pathname')
)
def update_page(path):
    if path == '/page_2':
        return page_2_layout()
    else:
        raise PreventUpdate

Hello @xychen,

It will still run through the pages, but it doesnt execute the code if you do something like this:

def layout():
    if not flask.request:
         return html.Div()
    ## rest of code

This will only run the code if there is a flask request, so there is someone actually browsing.

2 Likes

This might be interesting:

2 Likes

I was about to provide this link:

2 Likes

Hi @xychen

Pages automatically validates the layout as described here: Dynamically Create a Layout for Multi Page App Validation

You can turn this feature off by including suppress_callback_exceptions=True

app = Dash(__name__, use_pages=True, suppress_callback_exceptions=True)
1 Like

Hi @jinnyzor, @AIMPED, and @AnnMarieW,

Thanks for your help! They are so helpful. In my case, by add suppress_callback_exceptions=True will be able to get rid of those ‘ID not found in layout’ errors during initialization. if not flask.request is able to control the layout.

2 Likes