0
votes

I'm trying to build a multi-page app on Dash. I was able to get the index page come up on my localhost however, the content of the pages won't come up. Here's how my file structure looks like:

Multipage App (folder)
     apps (folder)
          __init__.py
          page1.py
          page2.py
     assets(folder)
     SQL (folder)
          data1.sql
          data2.sql
     app.py
     index.py
          

Here are the codes within the files:

app.py

import dash

# meta_tags are required for the app layout to be mobile responsive
app = dash.Dash(__name__, suppress_callback_exceptions=True, server=server
                )
server = app.server
 

index.py

import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

# Connect to main app.py file
from app import app
from app import server

# Connect to your app pages
from apps import page1, page2


app.layout = html.Div([
    html.Div([
        dcc.Link('Page 1', href='/page_1'),
        dcc.Link('Page 2', href='/page_2'),
    ], className="row"),
    dcc.Location(id='url', refresh=False),
    html.Div(id='page-content', children=[])
])


@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/page_1':
        return page1.layout
    if pathname == '/page_2':
        return page2.layout
    else:
        return "404 Page Error! Please choose a link"


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

page1.py

    from datetime import datetime as dt
    import dash
    from dash.dependencies import Input, Output
    import dash_table
    import dash_core_components as dcc
    import dash_html_components as html
    import plotly.express as px
    import pandas as pd
    import psycopg2
    import pathlib
    from app import app
    
    
    # connect to db
    conn = psycopg2.connect(
        host="localhost",
        database="postgres",
        user="postgres",
        port= "5432",
        password="example")
    
    # get relative data folder
    PATH = pathlib.Path(__file__).parent
    DATA_PATH = PATH.joinpath("../SQL").resolve()
    fd = open(DATA_PATH.joinpath("data1.sql", "r"))
    
    # read in the sql file
    sqlFile = fd.read()
    fd.close()

layout = html.Div(children=[
    dcc.Dropdown(
        id='demo-dropdown',
        options=[
            {'label': 'A', 'value': 1},
            {'label': 'B', 'value': 2},
            {'label': 'C', 'value': 3}
        ],
        value=1
    ),
    dash_table.DataTable(id='dd-output-container',
                         data=df.to_dict('records'),
                         columns=[{'id': c, 'name': c} for c in df.columns.values]) #
])
@app.callback(
    dash.dependencies.Output('dd-output-container', 'data'),
    [dash.dependencies.Input('demo-dropdown', 'value')])
def update_output(value):
    dfs = df.loc[df['numbers'] == value]
    return dfs.to_dict('records')

page2.py

    from datetime import datetime as dt
    import dash
    from dash.dependencies import Input, Output
    import dash_table
    import dash_core_components as dcc
    import dash_html_components as html
    import plotly.express as px
    import pandas as pd
    import psycopg2
    import pathlib
    from app import app
    
    
    # connect to db
    conn = psycopg2.connect(
        host="localhost",
        database="postgres",
        user="postgres",
        port= "5432",
        password="example")
    
    # get relative data folder
    PATH = pathlib.Path(__file__).parent
    DATA_PATH = PATH.joinpath("../SQL").resolve()
    fd = open(DATA_PATH.joinpath("data2.sql", "r"))
    
    # read in the sql file
    sqlFile = fd.read()
    fd.close()

layout = html.Div(children=[
    dcc.Dropdown(
        id='demo-dropdown',
        options=[
            {'label': 'A', 'value': 1},
            {'label': 'B', 'value': 2},
            {'label': 'C', 'value': 3}
        ],
        value=1
    ),
    dash_table.DataTable(id='dd-output-container',
                         data=df.to_dict('records'),
                         columns=[{'id': c, 'name': c} for c in df.columns.values]) #
])
@app.callback(
    dash.dependencies.Output('dd-output-container', 'data'),
    [dash.dependencies.Input('demo-dropdown', 'value')])
def update_output(value):
    dfs = df.loc[df['numbers'] == value]
    return dfs.to_dict('records')

Here's the error I am getting:

 File "index.py", line 29, in display_page
    return page2.layout
AttributeError: module 'apps.page2' has no attribute 'layout'

I want the content of the pages 1 and 2 to come up whenever someone clicks on the links. Right now, the links come up on the page and they are clickable, however, the content of the pages don't come up when I click on them. The URLs update as well when clicked. It's really just the content of the pages that I am having a problem with. Thank you!

1

1 Answers

0
votes

I got the similar error. In my case, there was a bug in my code in apps files which was only triggered during runtime. My guess is that there is also a runtime error triggered by a bug/typo in your page2.py. When you call return page2.layout, the error is triggered but the real error message was not returned. It ends up that page2 is not completely executed.

Try to print page2.layout somewhere in the index.py. It should return the real error message.