Chris Schmitz
Chris Schmitz

Reputation: 658

Dash: Multi-page app with same data across pages

I'm following the guidance to create a multi-page app in the dash documentation: https://dash.plotly.com/urls

My issue is that the data is in a total of four dataframes, and each of the three pages in my app uses more than one of these to visualize content. I'm trying to avoid reloading the dataframes each time I call one of the pages. Is this possible? How?

Currently, I'm trying to first load the df's using a function in my index.py, then load the other pages:

df_fz, df_md, df_auf, df_mat = get_dfs()
from apps import app1, app2, app3

[...]

@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/app1':
        return app1.layout
    elif pathname == '/app2':
        return app2.layout
    else:
        return app3.layout

Each of app1 to app3 uses the dataframes as if they were loaded at the top of their scripts, but this code as is is throwing an error because the df's are not defined. A minimal example of what app3 could look like:

layout = html.Div([
    html.H3('App 3'),
    dcc.Dropdown(
        id='app-3-dropdown',
        options=[
            {'label': 'App 3 - {}'.format(i), 'value': i} for i in [df_fz.Value]
        ]
    ),
    html.Div(id='app-3-display-value'),
])

@app.callback(
    Output('app-3-display-value', 'children'),
    [Input('app-3-dropdown', 'value')])
def display_value(value):
    return 'You have selected "{}" but in App 3'.format(value)

Upvotes: 4

Views: 8539

Answers (3)

Troy D
Troy D

Reputation: 2245

Looks like all you need to do is create a module that has your data that can be shared across different files.

data.py

import pandas as pd
df1 = pd.DataFrame()

app1.py

from data import df1

app2.py

from data import df1

module variables are global variables, so all of your files will be sharing the same df1, and since it's an import it'll run before the rest of your code in app, app1, etc.

You could also leave id='app-3-dropdown', options=[] at the start and then create the options list as a callback for 'app-3-dropdown'.

You can store your dataframe in dcc.Store(id='df-data', data=df.to_dict()), and that can be used as an Input or State for your other callbacks.

Upvotes: 3

user14891842
user14891842

Reputation: 1

If you're using the following file structure from https://dash.plotly.com/urls -

- app.py
- index.py
- apps
   |-- __init__.py
   |-- app1.py
   |-- app2.py

Try this approach of reading your dataframes in 'app.py' file. Since each of your 'app1.py', 'app2.py', 'app3.py' uses these dataframes, import the df's in these files, i.e. in your 'app1.py' code:

from app import app

from app import df_fz, df_md, df_auf, df_mat

Similarly for the other files.

Upvotes: -1

Adam Schroeder
Adam Schroeder

Reputation: 768

Try putting your dataframes inside a datasets folder and connect them inside each app page. Something like this:

PATH = pathlib.Path(__file__).parent
DATA_PATH = PATH.joinpath("../datasets").resolve()
df = pd.read_csv(DATA_PATH.joinpath("mydata.csv"))

Here's a tutorial on how to create a multipage app with Dash:

https://youtu.be/RMBSQ6leonU

Upvotes: 1

Related Questions