Frontend and Backend
- Load the components in the layout on server side
- Implement callbacks with default inputs on server side
- Open a session on web browser
- Load the components in the layout from server side to client side with outputs from default inputs
- Receive inputs from user interaction on client side, implment corresponding callbacks on server side, then return outputs to client side

Global Variable
- import dash
- import dash_core_components as dcc
- import dash_html_components as html
- from dash.dependencies import Input, Output, State
- from dash.exceptions import PreventUpdate
-
- external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
-
- app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
- server = app.server
-
- shared = None
-
- app.layout = html.Div([
- dcc.Input(value=shared, id = 'input'),
- html.H1(id = 'content'),
- ], className='container')
-
- @app.callback(
- Output('content', 'children'),
- Input('input', 'value')
- )
- def update_output_div(value):
- global shared
- temp = shared
- shared = value
- return temp
-
- app.scripts.config.serve_locally = True
-
- if __name__ == '__main__':
- app.run_server(debug=True)
-
Sessions share the same copy of the global variable
- # single worker
- python app.py
- or
- gunicorn app:server --workers 1
-

Each worker keeeps a copy of the global variable
May a different worker responses the request every time a session sends a request
As though a random global copy is returned
- # multiple workers
- gunicorn app:server --workers 8
-

Sharing Data Between Callbacks within a Single Session
Option 1. Each session access an independent file (database)

- import dash
- import dash_core_components as dcc
- import dash_html_components as html
- from dash.dependencies import Input, Output, State
- from dash.exceptions import PreventUpdate
- from os import path
-
- external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
-
- app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
- server = app.server
-
- app.layout = html.Div([
- dcc.Input(id = 'session_name'),
- dcc.Input(id = 'input'),
- html.H1(id = 'content'),
- html.Button('Click', id = 'button')
- ], className='container')
-
- @app.callback(
- Output('content', 'children'),
- Input('button', 'n_clicks'),
- State('input', 'value'),
- State('session_name', 'value')
- )
- def update_output_div(n_clicks, value, value_2):
- if not n_clicks:
- raise PreventUpdate
- if not path.exists(value_2):
- f = open(value_2, "w")
- f.write('Init')
- f.close()
- output_str = 'None'
- else:
- f = open(value_2, "r")
- output_str = f.readline()
- f.close()
- f = open(value_2, "w")
- f.write(str(value))
- f.close()
- return output_str
-
- if __name__ == '__main__':
- app.run_server(debug=True)
-
Option 2. In the user's browser session via dcc.Store
- Store the data in memory in the browser client
- Data will be transported over the network between each callback
- It's generally safe to store up to 2MB in most environments, and 5~10MB in most desktop-only applications

- import dash
- from dash.dependencies import Input, Output
- import dash_html_components as html
- import dash_core_components as dcc
-
- import pandas as pd
-
- df = pd.DataFrame({
- 'x': [1, 2, 3, 4, 5, 6],
- 'y': [3, 1, 2, 3, 5, 6],
- 'z': ['A', 'A', 'B', 'B', 'C', 'C']
- })
-
- app = dash.Dash()
-
- app.layout = html.Div([
- dcc.Dropdown(
- id='dropdown',
- options=[{'label': i, 'value': i} for i in ['A', 'B', 'C']],
- value='A'
- ),
- dcc.Graph(
- id='graph'
- ),
- dcc.Store(id='cache')
- ])
-
-
- @app.callback(Output('cache', 'data'), Input('dropdown', 'value'))
- def update_cache(value):
- filtered_df = df[df['z'] == value]
- return filtered_df.to_json()
-
-
- @app.callback(Output('graph', 'figure'), Input('cache', 'data'))
- def update_graph(cached_data):
- filtered_df = pd.read_json(cached_data)
- print(type(filtered_df))
- print(filtered_df)
- return {
- 'data': [{
- 'x': filtered_df['x'],
- 'y': filtered_df['y'],
- 'type': 'bar'
- }]
- }
-
-
- if __name__ == '__main__':
- app.run_server(debug=True)
-
- import dash
- import dash_core_components as dcc
- import dash_html_components as html
- from dash.dependencies import Input, Output, State
- from dash.exceptions import PreventUpdate
- import json
-
- external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
-
- app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
- server = app.server
-
- app.layout = html.Div([
- dcc.Input(id = 'input_1'),
- dcc.Input(id = 'input_2'),
- html.Div(id = 'content'),
- html.Button('Click', id = 'button'),
- dcc.Store(id='cache')
- ], className='container')
-
- @app.callback(
- Output('cache', 'data'),
- Input('button', 'n_clicks'),
- State('input_1', 'value'),
- State('input_2', 'value')
- )
- def update_cache_div(n_clicks, value, value_2):
- d = {'input_1': value, 'input_2': value_2}
- return d
-
- @app.callback(
- Output('content', 'children'),
- Input('cache', 'data'),
- )
- def update_output_div(d):
- dict_object = d
- return str(dict_object['input_1']) + ' '+str(dict_object['input_2'])
-
- if __name__ == '__main__':
- app.run_server(debug=True)
-
Option 3. Save in hidden div via the browser's DOM

- import dash
- import dash_core_components as dcc
- import dash_html_components as html
- from dash.dependencies import Input, Output, State
- from dash.exceptions import PreventUpdate
- import json
-
- external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
-
- app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
- server = app.server
-
- app.layout = html.Div([
- dcc.Input(id = 'input_1'),
- dcc.Input(id = 'input_2'),
- html.Div(id = 'content'),
- html.Button('Click', id = 'button'),
- html.Div(id='cache', style={'display': 'none'})
- ], className='container')
-
- @app.callback(
- Output('cache', 'children'),
- Input('button', 'n_clicks'),
- State('input_1', 'value'),
- State('input_2', 'value')
- )
- def update_cache_div(n_clicks, value, value_2):
- d = {'input_1': value, 'input_2': value_2}
- return json.dumps(d)
-
- @app.callback(
- Output('content', 'children'),
- Input('cache', 'children'),
- )
- def update_output_div(d):
- dict_object = json.loads(d)
- return str(dict_object['input_1']) + ' '+str(dict_object['input_2'])
-
- if __name__ == '__main__':
- app.run_server(debug=True)
-
Option 4. storing “global variables” in the cache on the server-side
- The expensive function will be run one time, the return will be saved in a global cache
- further calling will access the return from the global cache directly without repeating the expensive process

- import time
- import dash
- import dash_core_components as dcc
- import dash_html_components as html
- from dash.dependencies import Input, Output, State
- from dash.exceptions import PreventUpdate
- from os import path
- from flask_caching import Cache
-
- external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
-
- app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
- server = app.server
-
- cache = Cache(app.server, config={
- 'CACHE_TYPE': 'filesystem',
- 'CACHE_DIR': 'cache',
- 'CACHE_THRESHOLD': 200, # The maximum number of items the cache will store
- 'CACHE_DEFAULT_TIMEOUT': 60 # The default timeout, unit of time is seconds
- })
-
- app.layout = html.Div([
- dcc.Input(id = 'input'),
- html.Hr(),
- dcc.Loading(html.H1(id = 'content')),
- html.Button('Click', id = 'button'),
- html.Hr(),
- dcc.Loading(html.H1(id = 'content_2')),
- html.Button('Click 2', id = 'button2')
- ], className='container')
-
- # for the same parameter value, first call save results to cache
- # second and later calls will reuse the results
- # chaning the same parameter value, a new cache will be created
- @cache.memoize()
- def compute_expensive_data(value):
- time.sleep(5)
- return str(value)
-
- @app.callback(
- Output('content', 'children'),
- Input('button', 'n_clicks'),
- State('input', 'value')
- )
- def update_output_1(n_clicks, value):
- if not n_clicks:
- raise PreventUpdate
- return compute_expensive_data(value)
-
- @app.callback(
- Output('content_2', 'children'),
- Input('button2', 'n_clicks'),
- State('input', 'value')
- )
- def update_output_2(n_clicks, value):
- if not n_clicks:
- raise PreventUpdate
- return compute_expensive_data(value)
-
- if __name__ == '__main__':
- app.run_server(debug=True)
-
Reference