@irr3 wrote:
Hello,
it probably is a simple beginner mistake, but I try to explain what I think happens.
I have a multipage dash app running inside of a flask app.
It has the following structure:
├── app
│ ├── init.py
│ ├── tlc
│ │ ├── assets
│ │ │ ├── bootstrap.css
│ │ │ ├── custom.css
│ │ │ ├── favicon.ico
│ │ │ ├── responsive-sidebar.css
│ │ ├── callbacks.py
│ │ ├── data
│ │ │ ├── df_tlc_aktiva.csv
│ │ │ ├── df_tlc_passiva.csv
│ │ ├── pages
│ │ │ ├── app1.py
│ │ │ ├── app2.py
│ │ │ ├── app3.py
│ │ │ ├── app4.py
│ │ ├── sidebar.pyAll but one app{i}.py files have the following content, apart from different labels:
import dash_core_components as dcc import dash_html_components as html layout = html.Div([ html.H3('Income Statement'), dcc.Dropdown( id='app-2-dropdown', options=[ {'label': 'App1 - {}'.format(i), 'value': i} for i in [ 'NYC', 'MTL', 'LA' ] ] ), html.Div(id='app-2-display-value'), dcc.Link('Go to Balance Sheet', href='/dashboard/balancesheet') ])The one that is different, lets call it app4.py has the following content:
import dash_core_components as dcc import dash_html_components as html from dash.dependencies import Input, Output import dash_table import pandas as pd import pathlib # get relative data folder PATH = pathlib.Path(__file__).parent DATA_PATH = PATH.joinpath("../data").resolve() df_tlc_aktiva = pd.read_csv(DATA_PATH.joinpath("df_tlc_aktiva.csv"), sep=';') df_tlc_passiva = pd.read_csv(DATA_PATH.joinpath("df_tlc_passiva.csv"), sep=';') # read in layout = html.Div( [ html.H3('Balance Sheet'), html.H4('Aktiva'), # This datatable gets populated all over the place dash_table.DataTable( id='table', columns=[{"name": i, "id": i} for i in df_tlc_aktiva.columns], data=df_tlc_aktiva.to_dict('records'), ), html.H4('Passiva'), #This datatable is NOT populated all over the place dash_table.DataTable( id='table', columns=[{"name": i, "id": i} for i in df_tlc_passiva.columns], data=df_tlc_passiva.to_dict('records'), ), dcc.Dropdown( id='app-3-dropdown', options=[ {'label': 'Balance Sheet - {}'.format(i), 'value': i} for i in [ 'NYC', 'MTL', 'LA' ] ] ), html.Div(id='app-3-display-value'), dcc.Link('Go to Cashflow', href='/dashboard/cashflow') ])my callbacks are here in callbacks.py:
from datetime import datetime as dt import dash_bootstrap_components as dbc import dash_core_components as dcc import dash_html_components as html from dash.dependencies import Input, Output, State from .pages import ( quickcheck, incomeStatement, balanceSheet, cashflow, workingCapital, debt, indicators, shouldIs, model ) def register_callbacks(dashapp): # this callback uses the current pathname to set the active state of the # corresponding nav link to true, allowing users to tell see page they are on @dashapp.callback( [Output(f"page-{i}-link", "active") for i in range(1, 10)], [Input("url", "pathname")], ) def toggle_active_links(pathname): if pathname == "/dashboard": # Treat page 1 as the homepage / index return True, False, False return [pathname == f"/dashboard/page-{i}" for i in range(1, 10)] @dashapp.callback(Output("page-content", "children"), [Input("url", "pathname")]) def render_page_content(pathname): if pathname in ["/", "/dashboard/page-1"]: return quickcheck.layout elif pathname == "/dashboard/page-2": return incomeStatement.layout elif pathname == "/dashboard/page-3": return balanceSheet.layout elif pathname == "/dashboard/page-4": return cashflow.layout elif pathname == "/dashboard/page-5": return workingCapital.layout elif pathname == "/dashboard/page-6": return debt.layout elif pathname == "/dashboard/page-7": return indicators.layout elif pathname == "/dashboard/page-8": return shouldIs.layout elif pathname == "/dashboard/page-9": return model.layout # If the user tries to reach a different page, return a 404 message return dbc.Jumbotron( [ html.H1("404: Not found", className="text-danger"), html.Hr(), html.P(f"The pathname {pathname} was not recognised..."), ] ) @dashapp.callback( Output("sidebar", "className"), [Input("sidebar-toggle", "n_clicks")], [State("sidebar", "className")], ) def toggle_classname(n, classname): if n and classname == "": return "collapsed" return "" @dashapp.callback( Output("collapse", "is_open"), [Input("navbar-toggle", "n_clicks")], [State("collapse", "is_open")], ) def toggle_collapse(n, is_open): if n: return not is_open return is_open @dashapp.callback( Output('app-1-display-value', 'children'), [Input('app-1-dropdown', 'value')]) def display_value(value): return 'You have selected "{}"'.format(value) @dashapp.callback( Output('app-2-display-value', 'children'), [Input('app-2-dropdown', 'value')]) def display_value(value): return 'You have selected "{}"'.format(value) @dashapp.callback( Output('app-3-display-value', 'children'), [Input('app-3-dropdown', 'value')]) def display_value(value): return 'You have selected "{}"'.format(value) @dashapp.callback( Output('app-4-display-value', 'children'), [Input('app-4-dropdown', 'value')]) def display_value(value): return 'You have selected "{}"'.format(value)Then I have a sidebar that holds the navigation.
I register the callbacks on the dash instance like this in init.py:
def register_dashapps(app): from app.tlc.sidebar import layout from app.tlc.callbacks import register_callbacks # link fontawesome to get the chevron icons FA = "https://use.fontawesome.com/releases/v5.8.1/css/all.css" # Meta tags for viewport responsiveness meta_viewport = {"name": "viewport", "content": "width=device-width, initial-scale=1, shrink-to-fit=no"} tlc = dash.Dash(__name__, server=app, url_base_pathname='/dashboard/', assets_folder=get_root_path(__name__) + '/tlc/assets/', meta_tags=[meta_viewport], #external_stylesheets=[dbc.themes.SANDSTONE, FA], ) tlc.config.suppress_callback_exceptions = True with app.app_context(): tlc.title = 'TLC' tlc.layout = layout register_callbacks(tlc) _protect_dashviews(tlc)Current behaviour:
When I access the pages app1 to app3, everything works as expected, but when I access the page app4 with the dataframe and after that visit another page, let’s say app2, the first dataframe from app4.py is populated also on that page of app2, despite it’s not coded like that in the layout of the app2.
When I access the app4 page again, and then visit app2 again, it gets populated twice and so forth.
Only a hard reload of the whole page shows the actual layout that is supposed to show.
Expected behaviour:
Every app{i} should just show it’s own layout, and not anything from another app.
Any help would be appreciated, thanks!
Mark
Posts: 1
Participants: 1






