Black Lives Matter. Please consider donating to Black Girls Code today.

How to structure an app that updates on a page refresh

Hi.

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.

Thanks for any input.

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 :wink:

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)
1 Like