title: Python Dash refresh page not updating source data
body: <p>I have written a basic plotly dash app that pulls in data from a csv and displays it on a chart.
  You can then toggle values on the app and the graph updates.</p>
  <p>However, when I add new data to the csv (done once each day) the app doesn't update the data on refreshing the page.</p>
  <p>The fix is normally that you define your <code>app.layout</code> as a function, as outlined <a href="https://dash.plotly.com/live-updates" rel="nofollow noreferrer">here</a> (scroll down to updates on page load). You'll see in my code below that I've done that.</p>
  <p>Here's my code:</p>
  <pre><code>import dash
  import dash_core_components as dcc
  import dash_html_components as html
  from dash.dependencies import Input, Output
  import numpy as np
  
  import pandas as pd
  
  external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
  
  app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
  
  path = 'https://raw.githubusercontent.com/tbuckworth/Public/master/CSVTest.csv'
  
  df = pd.read_csv(path)
  df2 = df[(df.Map==df.Map)]
  
  
  def layout_function():
  
      df = pd.read_csv(path)
      df2 = df[(df.Map==df.Map)]
      
      available_strats = np.append('ALL',pd.unique(df2.Map.sort_values()))
      classes1 = pd.unique(df2[&quot;class&quot;].sort_values())
      metrics1 = pd.unique(df2.metric.sort_values())
      
      return html.Div([
              html.Div([
                  dcc.Dropdown(
                      id=&quot;Strategy&quot;,
                      options=[{&quot;label&quot;:i,&quot;value&quot;:i} for i in available_strats],
                      value=list(available_strats[0:1]),
                      multi=True
                  ),
                  dcc.Dropdown(
                      id=&quot;Class1&quot;,
                      options=[{&quot;label&quot;:i,&quot;value&quot;:i} for i in classes1],
                      value=classes1[0]
                  ),
                  dcc.Dropdown(
                      id=&quot;Metric&quot;,
                      options=[{&quot;label&quot;:i,&quot;value&quot;:i} for i in metrics1],
                      value=metrics1[0]
                  )],
              style={&quot;width&quot;:&quot;20%&quot;,&quot;display&quot;:&quot;block&quot;}),
                  
          html.Hr(),
      
          dcc.Graph(id='Risk-Report')          
      ])
              
  app.layout = layout_function
  
  
  @app.callback(
          Output(&quot;Risk-Report&quot;,&quot;figure&quot;),
          [Input(&quot;Strategy&quot;,&quot;value&quot;),
           Input(&quot;Class1&quot;,&quot;value&quot;),
           Input(&quot;Metric&quot;,&quot;value&quot;),
           ])
  
  def update_graph(selected_strat,selected_class,selected_metric):
      if 'ALL' in selected_strat:
          df3 = df2[(df2[&quot;class&quot;]==selected_class)&amp;(df2.metric==selected_metric)]
      else:
          df3 = df2[(df2.Map.isin(selected_strat))&amp;(df2[&quot;class&quot;]==selected_class)&amp;(df2.metric==selected_metric)]
      df4 = df3.pivot_table(index=[&quot;Fund&quot;,&quot;Date&quot;,&quot;metric&quot;,&quot;class&quot;],values=&quot;value&quot;,aggfunc=&quot;sum&quot;).reset_index()
      traces = []
      for i in df4.Fund.unique():
          df_by_fund = df4[df4[&quot;Fund&quot;] == i]
          traces.append(dict(
                  x=df_by_fund[&quot;Date&quot;],
                  y=df_by_fund[&quot;value&quot;],
                  mode=&quot;lines&quot;,
                  name=i
                  ))
      
      if selected_class=='USD':
          tick_format=None
      else:
          tick_format='.2%'
      
      return {
              'data': traces,
              'layout': dict(
                  xaxis={'type': 'date', 'title': 'Date'},
                  yaxis={'title': 'Values','tickformat':tick_format},
                  margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
                  legend={'x': 0, 'y': 1},
                  hovermode='closest'
              )
          }
      
  
  if __name__ == '__main__':
      app.run_server(debug=True)
  </code></pre>
  <p>Things I've tried</p>
  <ol>
  <li>Removing the initial <code>df = pd.read_csv(path)</code> before the <code>def layout_function():</code>. This results in an error.</li>
  <li>Creating a callback button to refresh the data using this code:</li>
  </ol>
  <pre><code>@app.callback(
          Output('Output-1','children'),
          [Input('reload_button','n_clicks')]        
          )
  
  def update_data(nclicks):
      if nclicks == 0:
          raise PreventUpdate
      else:
          df = pd.read_csv(path)
          df2 = df[(df.Map==df.Map)]
          return('Data refreshed. Click to refresh again')
  </code></pre>
  <p>This doesn't produce an error, but the button doesn't refresh the data either.</p>
  <ol start="3">
  <li>Defining <code>df</code> within the <code>update_graph</code> callback. This updates the data every time you toggle something, which is not practicable (my real data is &gt; 10^6 rows, so i don't want to read it in every time the user changes a toggle value)</li>
  </ol>
  <p>In short, i think that defining <code>app.layout = layout_function</code> should make this work, but it doesn't. What am I missing/not seeing?</p>
  <p>Appreciate any help.</p>