Multipage and variable sharing (dcc.Store)

Hi, I am converting my single page code to multi, and I have a couple of issues:
1- When I run page1 individually (with a couple of changes), it runs without an issue, for example, I can get the RadioItems displayed after pressing the submit button, with the multipage, nothing is happening.
2- When I apply the multipage setting, the callback seems not to be excuted.

So, the help that I need is in the following:
1- Execute all the pages, here I am giving only page1, but I will have a couple more
2- I want to share the RadioItems selection among all pages, so how do I setup the dcc.store?
3- Most likely I will need more sharing between other pages, do I need to set the dcc.store for each variable individually?
4- When I run the app.py, it runs and then starts the server, and then goes into the loop again (just one more time), not sure why.
5- The variable that I want to share is the nic_selection.

Help is highly appreciated, here are the codes for app.py and page1.py (by the way, if I run the multipage tutorials, it works fine, so I don’t think it is an issue of versions)

Thanks for the assistance

App.py

import dash
from dash import html, dcc
print('1')
app = dash.Dash(__name__, use_pages=True)
print('1.1')
app.layout = html.Div(
    [
        # main app framework
        html.Div("Python Multipage App with Dash", style={'fontSize':50, 'textAlign':'center'}),
        html.Div([
            dcc.Link(page['name']+"  |  ", href=page['path'])
            for page in dash.page_registry.values()
        ]),
        html.Hr(),
        # content of each page
        dash.page_container
    ]
)

print('1.2')
if __name__ == "__main__":
    print('1.3')
    app.run(debug=True)
    print('1.4')

page1.py

import dash
from dash import dcc, html, Input, Output, Dash, State
import pandas as pd
import os

dash.register_page(__name__, path='/')
app = Dash(__name__)
print('2')
os.system(f'cmd /c path/tshark -D > path/nics.txt')

nics = pd.read_csv(
    'path/nics.txt', sep="}", header=None)
nics.fillna(' (Loopback Link, DO NOT select)', inplace=True)
print('2.1')
# print(nics)
# print(nics[1])
# print(type(nics))
app.layout = html.Div([
    html.H1(children='Welcome to the Network Traffic Monitoring Dashboard', style={
            'text-align': 'center'}),
    html.Div([
        html.Label(['Please select a graph to start capturing Traffic, then move to page 2:'], style={
                   'font-weight': 'bold'}),
        dcc.RadioItems(
            id='nic_selection',
            options=nics[1]),
        html.Button(id='submit_btn', n_clicks=0, children='Submit'),
        html.Div(id='btn_output'),
        dcc.Store(id='selection_storage', storage_type='local')
    ])])
print(2.2)
layout = app.layout
print('2.7')


@app.callback(
    [Output('btn_output', 'children'),
     Output('selection_storage', 'data')],
    [State('nic_selection', 'value')],
    [Input('submit_btn', 'n_clicks')]
)
def update_output(value, n_clicks, data):
    print('2.3')
#    print('data is', data)
    if n_clicks == 0:
        print('2.4')
        raise PreventUpdate
        # return ''
        print('2.5')
    else:
        print('2.6')
    #     # selected_nic.to_csv("D:/OneDrive/NetPredict/codes/multipages/Output.txt")
        # text_file = open("D:/OneDrive/NetPredict/codes/multipages/Output.txt", "w")
        # text_file.write(data)
        # text_file.close()
    print('value is', value)


print('2.9')
if __name__ == "__main__":
    print('2.91')
    app.run_server(debug=True)
    print('2.92')

HI @arafeek,

@adamschroeder has a video about setting up a multipage app which answers some of your questions:

1 Like

Thanks, in fact his template is what I built my code on, I just replaced the layout and other things, (that is why I said it works with other examples) but the video does not answer my questions, maybe he has other ones that I need to watch, but definitely not this one.

Thanks anyway

I’m using my phone right now, but your page1 should look like this, without reference to app.

import dash
from dash import dcc, html, Input, Output, Dash, State, callback
import pandas as pd
import os

dash.register_page(__name__, path='/')

print('2')
os.system(f'cmd /c D:/OneDrive/NetPredict/dumpcap/tshark -D > D:/OneDrive/NetPredict/codes/multipages/nics.txt')

nics = pd.read_csv(
    'D:/OneDrive/NetPredict/codes/multipages/nics.txt', sep="}", header=None)
nics.fillna(' (Loopback Link, DO NOT select)', inplace=True)
print('2.1')
# print(nics)
# print(nics[1])
# print(type(nics))
layout = html.Div([
    html.H1(children='Welcome to the Network Traffic Monitoring Dashboard', style={
            'text-align': 'center'}),
    html.Div([
        html.Label(['Please select a graph to start capturing Traffic, then move to page 2:'], style={
                   'font-weight': 'bold'}),
        dcc.RadioItems(
            id='nic_selection',
            options=nics[1]),
        html.Button(id='submit_btn', n_clicks=0, children='Submit'),
        html.Div(id='btn_output'),
        dcc.Store(id='selection_storage', storage_type='local')
    ])])
print(2.2)


@callback(
    [Output('btn_output', 'children'),
     Output('selection_storage', 'data')],
    [State('nic_selection', 'value')],
    [Input('submit_btn', 'n_clicks')]
)
def update_output(value, n_clicks, data):
    print('2.3')
#    print('data is', data)
    if n_clicks == 0:
        print('2.4')
        raise PreventUpdate
        # return ''
        print('2.5')
    else:
        print('2.6')
    #     # selected_nic.to_csv("D:/OneDrive/NetPredict/codes/multipages/Output.txt")
        # text_file = open("D:/OneDrive/NetPredict/codes/multipages/Output.txt", "w")
        # text_file.write(data)
        # text_file.close()
    print('value is', value)
2 Likes

Thanks, this is one part, I started to get the result of the button displayed, however what I need is to use the dcc.store() to transfer that value to the other pages

hi @arafeek

To add to @AIMPED 's response, you can also take a look at Ann Marie’s dash-multi-page-app-demos. There are many examples there that I’ve learned from. The dcc.Store example is one of them. (make sure to put your dcc.Store in the app.py as well.)

2 Likes

Thanks Adam, I have an idea on the store now, but I have a couple of more questions:
1- If I have another variable that will be created and used in another page, I am assuming that I need to create a new dcc.store for it, so a store for each variable, is this correct?
2- When I select a value from the radio item of page one, it stores as expected, however if I go to another page and return to page one, the value is reset (None in my case), how do I prevent it and reserve the value until the submit button is pressed again. Based on the code I posted above

BTW, your videos are very informative, going through them gradually

Hi.

  1. In a clientside store you can store everything which is json serializable. So technically you could use one dcc.Store() containing an dictionary with all your variables as keys and update it every time. You could also use a separate dcc.Store() for each variable.

  2. Lot’s of dash core components have a persistence property. If you set this to true, the selection will be stored and you’ll see the selected value when returning to the page. See also
    Persisting User Preferences & Control Values | Dash for Python Documentation | Plotly

1 Like

Excellent, many thanks,

Now, MAYBE, this is my last question, at least for this topic
My main application is a multiprocessing code, it calls a couple of processes, how does dash works with MPing? because I know that some are not working with it, e.g. streaamlit does not.

The point is that I have the if __name__ == "__main__": in page2, which makes the app.run runs twice, if I cancel the first one, the app does not work and if I cancel the second, then my other functions will not work,

I just inserted my main code in that page but did not work as expected, no error messages yet, but I just want to have an advise rather than spending time debugging something that might not work.

e.g., should I move my multiprocessing calls to the App.py?

Any advise is highly appreciated