1
votes

I have a Dash app that makes some graphs based on data drawn from an API, and I'd like to give the user an option to change a parameter, pull new data based on this, and then redraw the graphs. It could be through a form, but I figured the simplest method would be to use the <pathname> route system from Flask. Dash allows me to do this:

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px

app = dash.Dash(__name__)
app.layout = html.Div(children=[
    dcc.Location(id='url', refresh=False),
    html.Div(id='page-content'),
])


@app.callback(dash.dependencies.Output('page-content', 'children'),
              [dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/':
        return html.Div('Please append a pathname to the route')
    else:
        data = get_data_from_api(int(pathname))
        fig_1 = px.line(data, x="time", y="price")
        fig_2 = px.line(data, x="time", y="popularity")
        return html.Div(children=[
                dcc.Graph(id='fig_1',figure=fig_1),
                dcc.Graph(id='fig_2',figure=fig_2),
            ])


if __name__ == '__main__':
    app.run_server(debug=True)

But the problem is that the API call takes a minute or two, and it seems to be constantly polling it, such that the request times out and and the graphs never redraw. What I need is something which doesn't auto-refresh, which can run the API call, update the underlying data, and then tell the app to refresh its state.

I did consider a Dash-within-Flask hybrid like this, but it seems excessively complicated for my use-case. Is there a simpler way to do this?

1
Have you considered using an interval timer? Dash core components has an interval: dcc.Interval(id="example-interval", interval=10000) Then you can use "example-interval" as an input to a callbackTom
will try and report back, thanks!Josh Friedlander

1 Answers

1
votes

I think you can add a html.Button to your layout.

html.Button('Update', id='update-button')

To your Callback you can add:

@app.callback(dash.dependencies.Output('page-content', 'children'),
          [dash.dependencies.Input('url', 'pathname'),
           dash.dependencies.Input('update-button', 'n_clicks')])
def display_page(pathname, n_clicks):
    ....

No need to process the variabel n_clicks in anyway. The Callback is always triggerd.

Cheers