I'm trying to replicate "multi_page_example1" from https://github.com/AnnMarieW/dash-multi-page-app-demos/tree/main. This uses a drop-down menu to navigate to different pages.
However, I want to adjust the navbar options to be the standard links as in the first example here: https://dash-bootstrap-components.opensource.faculty.ai/docs/components/navbar/
A simple example is below:
Folder structure:
- app.py
- app_pages
|-- home.py
|-- data_upload.py
|-- __init__.py
home.py:
import dash
from dash import html
dash.register_page(__name__, path = '/')
layout = html.Div(children=[
html.H1(children='This is our Home page')
])
data_upload.py:
import dash
from dash import html
dash.register_page(__name__)
layout = html.Div(children=[
html.H1(children='This is our upload page')
])
app.py:
import dash_bootstrap_components as dbc
import dash
app = dash.Dash(__name__,
pages_folder = "app_pages",
use_pages = True,
external_stylesheets=[dbc.themes.BOOTSTRAP])
navbar = dbc.NavbarSimple(
children=[
dbc.NavItem(dbc.NavLink("Home", href="/home")),
dbc.NavItem(dbc.NavLink("Data upload", href="/data_upload")),
],
brand="Multipage Dash App",
color="dark",
dark=True,
className="mb2",
)
app.layout = dbc.Container(
[navbar, dash.page_container],
fluid = True)
if __name__ == "__main__":
app.run_server(debug=False)
Problems:
I have to run the app with "debug=False
" because the server won't launch Dash otherwise.
When it launches I can see the basic web app with navbar links. However, clicking between pages generates a "404 - Page not found" message. Oddly, the home page displays the normal message initially, but the 404 after clicking between links.
Where am I going wrong?
This is my first time working with bootstrap components and Dash multi-page approaches. I'm hoping to re-configure my current tabs-only Dash web app to a multi-page app with tab layouts in individual pages.
app.py
file example demonstrating a multi-page Dash web appNote: You can of course extend this approach with >1 files, as you wish, so long as ensuring correct modularization & importing (e.g., of the
dash.Dash
app object, separate page layouts, callbacks, etc.).
Below, the layouts for the "Home" and "Data upload" pages are defined within the same file along with a callback that updates the 'page-content
' container based on the current URL path via dcc.Location
.
from dash import Dash, Input, Output
from dash import html, dcc
import dash_bootstrap_components as dbc
home_layout = html.Div(children=[html.H1(children="This is our Home page")])
data_upload_layout = html.Div(
children=[html.H1(children="This is our upload page")]
)
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
navbar = dbc.NavbarSimple(
children=[
dbc.NavItem(dbc.NavLink("Home", href="/")),
dbc.NavItem(dbc.NavLink("Data upload", href="/data_upload")),
],
brand="Multipage Dash App",
color="dark",
dark=True,
className="mb-2",
)
app.layout = html.Div(
[
dcc.Location(id="url", refresh=False),
navbar,
dbc.Container(id="page-content", className="mb-4", fluid=True),
]
)
@app.callback(Output("page-content", "children"), Input("url", "pathname"))
def display_page(pathname):
if pathname == "/":
return home_layout
elif pathname == "/data_upload":
return data_upload_layout
else:
return dbc.Jumbotron(
[
html.H1("404: Not found", className="text-danger"),
html.Hr(),
html.P(f"The pathname {pathname} was not recognized..."),
]
)
if __name__ == "__main__":
app.run_server(debug=True)
ā produces this app behavior: