Multiple Users can't access local dash app

I am executing a dash app as a flask app. I’m simulating different users changing the URL in order to get different data. E.g: http://localhost:1234/dash?username=user1, http://localhost:1234/dash?username=user2, etc I’m using intermediate callbacks as described in the example 1: Part 5. Sharing Data Between Callbacks | Dash for Python Documentation | Plotly The problem I’m getting is that apparently, the callback or the function is been executed ONLY at the very first time a user enter the URL.
I’m not posting the whole solution but I think you can get the idea. I have a function that reads and filter the data depending on the user coming from the URL, the layout with some dropdowns, charts and table and the callbacks with their functions.
main.py

from flask import request

from src.globals import try_log, server
from src.module.application.service.dashboard_service import DashboardApplication 

@server.route("/dash", methods=['GET','POST'])
@try_log
def load_dash():      
    """_summary_

    Args:
        username (str): _description_
    """
    params = request.args
    if params['username']:
        service: DashboardApplication = DashboardApplication()    
        app = service.load_asm(user=params['username']) 
        return app.index() 

if __name__ == '__main__':
    server.run(host = '0.0.0.0')

app_service.py

def create_dash(self,df1,df2,user):
   df_1['Of ID'] = df_res_agua['Oficina ID'].astype(float).astype('Int64')
   df_2['Of ID'] = df_res_emision['Ofi ID'].astype(float).astype('Int64')
   
   app.layout = html.Div([
    dcc.Store(id='intermediate-value'),
    html.Div(children=[
        html.Div(                                                   
                    dcc.Dropdown(
                        id="region-filter",                            
                        className="dropdown",                                                           
                        placeholder="Region",      
                    ), className="dropdown-item"                       
                ),
                .....some others dropdowns,
                .....charts and tables
    ])
 ], className='myclass')

    @app.callback(
            Output('intermediate-value', 'data'),
            Input('region-filter', 'value'),
            Input('pais-filter', 'value'),
            Input('division-filter', 'value'),
            Input('sociedad-filter', 'value'), 
            Input('oficina-filter', 'value')
        )
   def clean_data(selregion,selctry,seldivision,selsoc,selofi):
     return filter_data()
######## Start Dropdowns Callbacks#######
   @app.callback( 
            Output('region-filter', 'children'),
            Input('intermediate-value', 'data') 
        ) 
   def update_output_region_options(data_reg_json):
    print("###########Execute Callback KPI Region#############")
    datasets = json.loads(data_reg_json)
    region = np.array(pd.read_json(datasets['Region'], orient='split')).ravel() 
    return [{'label': i, 'value': i} for i in region]

And the traceback: When the first user who loads the app it is displayed as a charm and I get the “200” code response. Then, when the second, third, etc. loads the app, I’m getting the code response “304” and it seems the callbacks are not being executed, so that, it is not showing any data on the charts

127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /dash?username=user1 HTTP/1.1" 200 - --First load with the user
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /assets/style.css?m=1661938436.611051 HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/deps/polyfill@7.v2_6_2m1664448141.12.1.min.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /assets/style.css HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/deps/react@16.v2_6_2m1664448141.14.0.min.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/deps/react-dom@16.v2_6_2m1664448141.14.0.min.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/deps/prop-types@15.v2_6_2m1664448141.8.1.min.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_6_2m1664448141.min.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/dcc/dash_core_components.v2_6_2m1664448141.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/dcc/dash_core_components-shared.v2_6_2m1664448141.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/html/dash_html_components.v2_0_5m1664448142.min.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/dash_table/bundle.v5_1_6m1664448141.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-layout HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-dependencies HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_favicon.ico?v=2.6.2 HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /assets/LogoApplusCOM.png HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/dcc/async-dropdown.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/dcc/async-graph.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/dcc/async-plotlyjs.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/dash_table/async-table.js HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:37] "GET /_dash-component-suites/dash/dash_table/async-highlight.js HTTP/1.1" 200 -
###########Execute Callback Intermediate#############
127.0.0.1 - - [30/Sep/2022 01:49:38] "POST /_dash-update-component HTTP/1.1" 200 -
###########Execute Callback CHART#############
###########Execute Callback KPIS#############
127.0.0.1 - - [30/Sep/2022 01:49:42] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:42] "POST /_dash-update-component HTTP/1.1" 200 -
c:\Users\me\Dash\Test\src\module\business\service\dashboard_service.py:628: FutureWarning:

The default value of numeric_only in DataFrameGroupBy.sum is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function.

###########Execute Callback dropdown Region#############127.0.0.1 - - [30/Sep/2022 01:49:42] "POST /_dash-update-component HTTP/1.1" 200 -

127.0.0.1 - - [30/Sep/2022 01:49:42] "POST /_dash-update-component HTTP/1.1" 200 -
Dropdown-Region:  ['Africa' 'Asia Pacific' 'Latin America' 'Mediterranean' 'Middle East'
 'North America' 'Northern Europe']127.0.0.1 - - [30/Sep/2022 01:49:42] "POST /_dash-update-component HTTP/1.1" 200 -

127.0.0.1 - - [30/Sep/2022 01:49:42] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:49:43] "POST /_dash-update-component HTTP/1.1" 200 -
c:\Users\me\Dash\Test\src\module\business\service\dashboard_service.py:137: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /dash?username=user2 HTTP/1.1" 200 -  ---When I change the parameter to set another user.
127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /assets/style.css HTTP/1.1" 304 -
127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /assets/style.css?m=1661938436.611051 HTTP/1.1" 304 -
127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /_dash-layout HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /_dash-dependencies HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /_favicon.ico?v=2.6.2 HTTP/1.1" 200 -
127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /assets/LogoApplusCOM.png HTTP/1.1" 304 -
127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /_dash-component-suites/dash/dcc/async-dropdown.js HTTP/1.1" 304 -
127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /_dash-component-suites/dash/dcc/async-graph.js HTTP/1.1" 304 -
127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /_dash-component-suites/dash/dash_table/async-highlight.js HTTP/1.1" 304 -
127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /_dash-component-suites/dash/dash_table/async-table.js HTTP/1.1" 304 -
127.0.0.1 - - [30/Sep/2022 01:50:10] "GET /_dash-component-suites/dash/dcc/async-plotlyjs.js HTTP/1.1" 304 -

My question is, how can I handle multiple users? Do I need to specifiy when to update the app or am I missing something? When these callbacks are executed after another user from another machine or even another explorer try to load the app?
As mentioned in Part 5. Sharing Data Between Callbacks | Dash for Python Documentation | Plotly on the Example 1

  • If you open up a new browser window, the app’s callbacks will always re-compute the data. The data is only cached between callbacks within the same session.
    which t means it will do it automatically, isn’t it?

@danimelv,

Typically, if you want to have dynamic users you will build the layout based upon each request. This can be done by having an overall app.layout, within that you have a div which will be filled based upon a callback specific to the user.

app.layout = html.Div([dcc.Location(id='url'), html.Div(id='page-content')])

@app.callback (
    Output('page-content','children'),
    Input('url','pathname')
)
def loadPages(pathname):
    if '/dash' in pathname:
        if 'username' in pathname:
           return service.load_asm(user=paras['username'])
   return 'Sorry, unknown request'

Something along these lines. Now, if you are talking about cant access the url overall, you’ll need either a reverse proxy or if it is all on the same network, you’ll need to pass the ip=‘0.0.0.0’ in order to make it externally accessible.

Hi, @jinnyzor Thanks for taking the time to answer.
I did what you mention and still nothing happened. Also, I was trying to play with dcc.Location in order to trigger the callbacks everytime the URL changes, but still not working.

app.layout = html.Div([ 
            # dcc.Store stores the intermediate value
            dcc.Store(id='intermediate-value'),
            dcc.Location(id='url', refresh=False),
            html.Div( children=[ ...some dropdownshere ],
                    className="menu wrapper", 
                ),
            html.Div( children=[ ...some charts and tables here ],
                    className="menu wrapper", 
                ),    
        ], className='container')
################################ INTERMEDIATE CALLBACK ###############################
@app.callback(
            Output('intermediate-value', 'data'),
            Input('region-filter', 'value'),
            Input('ctry-filter', 'value'),
            Input('division-filter', 'value'),
            Input('society-filter', 'value'), 
            Input('office-filter', 'value'),
            Input('url', 'search')
        )   
def clean_data(selregion,selpais,seldivision,selsoc,selofi,url_us):        
    print("URL ES: ", url_us)     
    return get_data()
@app.callback( 
            Output('region-filter', 'options'),
            Input('intermediate-value', 'data'),
            Input('url', 'search')
        ) 
def update_output_region_options(data_reg_json,url_us):
    print("URL REGION: ", url_us)
    datasets = json.loads(data_reg_json)
    region = np.array(pd.read_json(datasets['Region'], orient='split')).ravel()
    return [{'label': i, 'value': i} for i in region]    

.... more callbacks   

The output I get: Please note, the first call to the URL is working (for user1)- “POST /_dash-update-component” is being executed.

A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  df_table.rename(columns={'Año':'Year',
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /dash?username=user1 HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /assets/style.css HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /assets/style.css?m=1661938436.611051 HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /_dash-component-suites/dash/deps/polyfill@7.v2_6_2m1664448141.12.1.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /_dash-component-suites/dash/deps/react@16.v2_6_2m1664448141.14.0.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /_dash-component-suites/dash/deps/react-dom@16.v2_6_2m1664448141.14.0.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /_dash-component-suites/dash/deps/prop-types@15.v2_6_2m1664448141.8.1.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_6_2m1664448141.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /_dash-component-suites/dash/dcc/dash_core_components.v2_6_2m1664448141.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /_dash-component-suites/dash/dcc/dash_core_components-shared.v2_6_2m1664448141.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /_dash-component-suites/dash/html/dash_html_components.v2_0_5m1664448142.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:12] "GET /_dash-component-suites/dash/dash_table/bundle.v5_1_6m1664448141.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:13] "GET /_dash-layout HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:13] "GET /_dash-dependencies HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:13] "GET /_favicon.ico?v=2.6.2 HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:13] "GET /assets/LogoApplusCOM.png HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:13] "GET /_dash-component-suites/dash/dcc/async-dropdown.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:13] "GET /_dash-component-suites/dash/dcc/async-graph.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:13] "GET /_dash-component-suites/dash/dcc/async-plotlyjs.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:13] "GET /_dash-component-suites/dash/dash_table/async-highlight.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:13] "GET /_dash-component-suites/dash/dash_table/async-table.js HTTP/1.1" 200 -
URL ES:  ?username=user1
127.0.0.1 - - [03/Oct/2022 23:10:14] "POST /_dash-update-component HTTP/1.1" 200 -
URL CHARTS:  ?username=user1
URL OFIC:  127.0.0.1 - - [03/Oct/2022 23:10:15] "POST /_dash-update-component HTTP/1.1" 200 -
?username=user1
127.0.0.1 - - [03/Oct/2022 23:10:15] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:15] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:15] "POST /_dash-update-component HTTP/1.1" 200 -
URL REGION:  ?username=user1
127.0.0.1 - - [03/Oct/2022 23:10:15] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:15] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:10:15] "POST /_dash-update-component HTTP/1.1" 200 -
c:\Users\xxx\Documents\Data Visualization\PoC\DashDinamico\src\module\business\service\dashboard_service.py:133: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

---This is the output when I open another tab with different user/url:

127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /dash?username=user2 HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /assets/style.css HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/deps/react@16.v2_6_2m1664448141.14.0.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/deps/react-dom@16.v2_6_2m1664448141.14.0.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/deps/polyfill@7.v2_6_2m1664448141.12.1.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /assets/style.css?m=1661938436.611051 HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/deps/prop-types@15.v2_6_2m1664448141.8.1.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_6_2m1664448141.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/dcc/dash_core_components-shared.v2_6_2m1664448141.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/dcc/dash_core_components.v2_6_2m1664448141.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/html/dash_html_components.v2_0_5m1664448142.min.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/dash_table/bundle.v5_1_6m1664448141.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-layout HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-dependencies HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_favicon.ico?v=2.6.2 HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/dcc/async-dropdown.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/dcc/async-graph.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/dash_table/async-highlight.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/dash_table/async-table.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /_dash-component-suites/dash/dcc/async-plotlyjs.js HTTP/1.1" 200 -
127.0.0.1 - - [03/Oct/2022 23:11:07] "GET /assets/LogoApplusCOM.png HTTP/1.1" 200 -

What am I missing?

Is your goal to update the charts? Right now, it only looks like you are updating some options and the intermediate-value.

Please note, for the second callback, change the url search to a “State”, as you dont want that one to be triggered by an update to the url.

My goal is to update the whole page everytime a new URL is been modified (given that it means there is a new user)

@danimelv Unless you implement your login, I think is not possible to make it. I think what you are trying to do is “embed” the app into an already application, so that you don’t need to handle again a login, isn’t ti?

@danimelv,

You need to make your user defined layout be a function that you call from a callback. This callback outputs to an div’s children that is in the app layout.

Here is a very simple exmaple:

import dash
from dash import Input, Output, State, html, dcc, dash_table

app = dash.Dash(
    __name__
)

app.layout = html.Div([
        dcc.Location(id='url', refresh=False),
        html.Div(id='page-content'),
])

@app.callback(
    Output("page-content","children"),
    Input('url','pathname')
)
def userPages(path):
    if path and not path == '/':
        #### put your page's layout function here
        return 'Welcome user: ' + path.split('/')[1]
    return "Welcome to my page, I dont know who you are"



if __name__ == "__main__":
    app.run_server(debug=True)

image

image