I’ve got a dashboard that gets data from an external CSV file. I’ve noticed that the data is only updated when the app is restarted and not when the page is refreshed. I’ve read the doc on “Updates on Page Load” and this post
However, my needs are a little more complex. My app basically does the following steps:
1/ get csv data
2/ put csv data into a dataframe
4/ generate various pivot tables and dictionaries (for the dropdowns)
5 /display graphs, dropdowns and tables
I’d like to avoid using global variables but I’m not sure on how to best structure the app.
If I use “app.layout = serve_layout”, serve_layout is called on a page refresh but I cannot pass anything to that function (like values from dropdowns, dataframe, etc…)
If I use “app.layout = serve_layout(df)”, then serve_layout is not called on a page refresh.
I do not want to have steps 1 to 4 in the callbacks as I only want to the update the csv/pivots on a page refresh.
I hope it makes some sense. I could put some code if that helps but I have 7 dcc.Graph/dcc.Dropdown and 5 html.Table, so it’s a bit long.
you could try having steps 1-4 in a callback initiated by a button or something…
would be nice if dash had like an init function or a callback upon refresh… i dont think that exists yet though.
Thanks for the reply. That could be a workaround I guess but I’d really like what would be the best way to tackle this without adding an extra button. A button feels like superfluous from a UX perspective. I’m very new to this so it’d a great learning experience for me.
Here’s a simpler example of what I’m doing. The data in the example is meaningless and is purely for demonstration purpose
import dash
import pandas as pd
from dash import Dash
import plotly.graph_objs as go
import dash_core_components as dcc
import dash_html_components as html
from flask import Flask
def open_csv_data():
df = pd.read_csv('test_csv.csv')
return df
def compute_data(df):
df.columns = [col.replace(' ', '_').lower() for col in df.columns]
df.columns = [col.replace('-', '_').lower() for col in df.columns]
all_regions = df['region'].unique()
return all_regions
def get_number_people_per_region(df):
df_pv_number_people_per_region = df.pivot_table(index='region', aggfunc='count')
df_pv_number_people_per_region.drop(df_pv_number_people_per_region.columns[1:], axis=1, inplace=True)
df_pv_number_people_per_region.columns = ['Nb of people']
return df_pv_number_people_per_region
def generate_table(df, max_rows=10):
df = df.reset_index()
return html.Table(
[html.Tr([html.Th(col) for col in df.columns])] +
[html.Tr([
html.Td(df.iloc[i][col]) for col in df.columns
], className='dash-table') for i in range(min(len(df), max_rows))]
)
def app_layout(all_regions, df_pv_regions_most_people):
return html.Div([
html.Div([
dcc.Dropdown(
id="dd-regions",
options=[{
'label': i,
'value': i
} for i in all_regions],
value=all_regions[0]),
dcc.Graph(id='graph-regions'),
]),
html.Div([
generate_table(df_pv_regions_most_people)
]),
])
server = Flask(__name__)
app = Dash(server=server)
df = open_csv_data()
all_regions = compute_data(df)
df_pv_regions_most_people = get_number_people_per_region(df)
app.layout = app_layout(all_regions, df_pv_regions_most_people)
@app.callback(
dash.dependencies.Output('graph-regions', 'figure'),
[dash.dependencies.Input('dd-regions', 'value')])
def teams_graph(region_selected):
df_plot = df[df['region'] == region_selected]
df_plot_pv = df_plot.pivot_table(index = 'region', values='last_name', aggfunc='count')
return {
'data': [
go.Bar(
x=[1,],
y=[df_plot_pv.last_name.iloc[0],]
)],
'layout': go.Layout(
barmode='stack')
}
if __name__ == '__main__':
app.run_server(debug=True)