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

Global Variable
  1. import dash
  2. import dash_core_components as dcc
  3. import dash_html_components as html
  4. from dash.dependencies import Input, Output, State
  5. from dash.exceptions import PreventUpdate
  6.  
  7. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
  8.  
  9. app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
  10. server = app.server
  11.  
  12. shared = None
  13.  
  14. app.layout = html.Div([
  15. dcc.Input(value=shared, id = 'input'),
  16. html.H1(id = 'content'),
  17. ], className='container')
  18.  
  19. @app.callback(
  20. Output('content', 'children'),
  21. Input('input', 'value')
  22. )
  23. def update_output_div(value):
  24. global shared
  25. temp = shared
  26. shared = value
  27. return temp
  28.  
  29. app.scripts.config.serve_locally = True
  30.  
  31. if __name__ == '__main__':
  32. app.run_server(debug=True)
  • Sessions share the same copy of the global variable
    1. # single worker
    2. python app.py
    3. or
    4. 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
    1. # multiple workers
    2. gunicorn app:server --workers 8

    Sharing Data Between Callbacks within a Single Session
  • Option 1. Each session access an independent file (database)
    1. import dash
    2. import dash_core_components as dcc
    3. import dash_html_components as html
    4. from dash.dependencies import Input, Output, State
    5. from dash.exceptions import PreventUpdate
    6. from os import path
    7.  
    8. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
    9.  
    10. app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
    11. server = app.server
    12.  
    13. app.layout = html.Div([
    14. dcc.Input(id = 'session_name'),
    15. dcc.Input(id = 'input'),
    16. html.H1(id = 'content'),
    17. html.Button('Click', id = 'button')
    18. ], className='container')
    19.  
    20. @app.callback(
    21. Output('content', 'children'),
    22. Input('button', 'n_clicks'),
    23. State('input', 'value'),
    24. State('session_name', 'value')
    25. )
    26. def update_output_div(n_clicks, value, value_2):
    27. if not n_clicks:
    28. raise PreventUpdate
    29. if not path.exists(value_2):
    30. f = open(value_2, "w")
    31. f.write('Init')
    32. f.close()
    33. output_str = 'None'
    34. else:
    35. f = open(value_2, "r")
    36. output_str = f.readline()
    37. f.close()
    38. f = open(value_2, "w")
    39. f.write(str(value))
    40. f.close()
    41. return output_str
    42.  
    43. if __name__ == '__main__':
    44. app.run_server(debug=True)
  • Option 2. In the user's browser session via dcc.Store
    1. import dash
    2. from dash.dependencies import Input, Output
    3. import dash_html_components as html
    4. import dash_core_components as dcc
    5.  
    6. import pandas as pd
    7.  
    8. df = pd.DataFrame({
    9. 'x': [1, 2, 3, 4, 5, 6],
    10. 'y': [3, 1, 2, 3, 5, 6],
    11. 'z': ['A', 'A', 'B', 'B', 'C', 'C']
    12. })
    13.  
    14. app = dash.Dash()
    15.  
    16. app.layout = html.Div([
    17. dcc.Dropdown(
    18. id='dropdown',
    19. options=[{'label': i, 'value': i} for i in ['A', 'B', 'C']],
    20. value='A'
    21. ),
    22. dcc.Graph(
    23. id='graph'
    24. ),
    25. dcc.Store(id='cache')
    26. ])
    27.  
    28.  
    29. @app.callback(Output('cache', 'data'), Input('dropdown', 'value'))
    30. def update_cache(value):
    31. filtered_df = df[df['z'] == value]
    32. return filtered_df.to_json()
    33.  
    34.  
    35. @app.callback(Output('graph', 'figure'), Input('cache', 'data'))
    36. def update_graph(cached_data):
    37. filtered_df = pd.read_json(cached_data)
    38. print(type(filtered_df))
    39. print(filtered_df)
    40. return {
    41. 'data': [{
    42. 'x': filtered_df['x'],
    43. 'y': filtered_df['y'],
    44. 'type': 'bar'
    45. }]
    46. }
    47.  
    48.  
    49. if __name__ == '__main__':
    50. app.run_server(debug=True)
    1. import dash
    2. import dash_core_components as dcc
    3. import dash_html_components as html
    4. from dash.dependencies import Input, Output, State
    5. from dash.exceptions import PreventUpdate
    6. import json
    7.  
    8. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
    9.  
    10. app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
    11. server = app.server
    12.  
    13. app.layout = html.Div([
    14. dcc.Input(id = 'input_1'),
    15. dcc.Input(id = 'input_2'),
    16. html.Div(id = 'content'),
    17. html.Button('Click', id = 'button'),
    18. dcc.Store(id='cache')
    19. ], className='container')
    20.  
    21. @app.callback(
    22. Output('cache', 'data'),
    23. Input('button', 'n_clicks'),
    24. State('input_1', 'value'),
    25. State('input_2', 'value')
    26. )
    27. def update_cache_div(n_clicks, value, value_2):
    28. d = {'input_1': value, 'input_2': value_2}
    29. return d
    30.  
    31. @app.callback(
    32. Output('content', 'children'),
    33. Input('cache', 'data'),
    34. )
    35. def update_output_div(d):
    36. dict_object = d
    37. return str(dict_object['input_1']) + ' '+str(dict_object['input_2'])
    38.  
    39. if __name__ == '__main__':
    40. app.run_server(debug=True)
  • Option 3. Save in hidden div via the browser's DOM
    1. import dash
    2. import dash_core_components as dcc
    3. import dash_html_components as html
    4. from dash.dependencies import Input, Output, State
    5. from dash.exceptions import PreventUpdate
    6. import json
    7.  
    8. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
    9.  
    10. app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
    11. server = app.server
    12.  
    13. app.layout = html.Div([
    14. dcc.Input(id = 'input_1'),
    15. dcc.Input(id = 'input_2'),
    16. html.Div(id = 'content'),
    17. html.Button('Click', id = 'button'),
    18. html.Div(id='cache', style={'display': 'none'})
    19. ], className='container')
    20.  
    21. @app.callback(
    22. Output('cache', 'children'),
    23. Input('button', 'n_clicks'),
    24. State('input_1', 'value'),
    25. State('input_2', 'value')
    26. )
    27. def update_cache_div(n_clicks, value, value_2):
    28. d = {'input_1': value, 'input_2': value_2}
    29. return json.dumps(d)
    30.  
    31. @app.callback(
    32. Output('content', 'children'),
    33. Input('cache', 'children'),
    34. )
    35. def update_output_div(d):
    36. dict_object = json.loads(d)
    37. return str(dict_object['input_1']) + ' '+str(dict_object['input_2'])
    38.  
    39. if __name__ == '__main__':
    40. app.run_server(debug=True)
  • Option 4. storing “global variables” in the cache on the server-side
    1. import time
    2. import dash
    3. import dash_core_components as dcc
    4. import dash_html_components as html
    5. from dash.dependencies import Input, Output, State
    6. from dash.exceptions import PreventUpdate
    7. from os import path
    8. from flask_caching import Cache
    9.  
    10. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
    11.  
    12. app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
    13. server = app.server
    14.  
    15. cache = Cache(app.server, config={
    16. 'CACHE_TYPE': 'filesystem',
    17. 'CACHE_DIR': 'cache',
    18. 'CACHE_THRESHOLD': 200, # The maximum number of items the cache will store
    19. 'CACHE_DEFAULT_TIMEOUT': 60 # The default timeout, unit of time is seconds
    20. })
    21.  
    22. app.layout = html.Div([
    23. dcc.Input(id = 'input'),
    24. html.Hr(),
    25. dcc.Loading(html.H1(id = 'content')),
    26. html.Button('Click', id = 'button'),
    27. html.Hr(),
    28. dcc.Loading(html.H1(id = 'content_2')),
    29. html.Button('Click 2', id = 'button2')
    30. ], className='container')
    31.  
    32. # for the same parameter value, first call save results to cache
    33. # second and later calls will reuse the results
    34. # chaning the same parameter value, a new cache will be created
    35. @cache.memoize()
    36. def compute_expensive_data(value):
    37. time.sleep(5)
    38. return str(value)
    39.  
    40. @app.callback(
    41. Output('content', 'children'),
    42. Input('button', 'n_clicks'),
    43. State('input', 'value')
    44. )
    45. def update_output_1(n_clicks, value):
    46. if not n_clicks:
    47. raise PreventUpdate
    48. return compute_expensive_data(value)
    49.  
    50. @app.callback(
    51. Output('content_2', 'children'),
    52. Input('button2', 'n_clicks'),
    53. State('input', 'value')
    54. )
    55. def update_output_2(n_clicks, value):
    56. if not n_clicks:
    57. raise PreventUpdate
    58. return compute_expensive_data(value)
    59.  
    60. if __name__ == '__main__':
    61. app.run_server(debug=True)
    Reference
  • Flask-Caching
  • Hidden Div