How to prevent callback from executing during refresh the app?

Hi Sir,

When i run my app, the callback run immediately to download the stocks from yahoo. Is there a way to prevent the callback to run unless i click on the update stock button? Thank you. Here is my code.

import os
import pandas_datareader.data as web
import pandas as pd
import datetime as dt
import plotly.graph_objs as go
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import time

external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]
app = dash.Dash(name, external_stylesheets=external_stylesheets)
default_path = os.path.dirname(os.path.realpath(‘file’))

INCREASING_COLOR = ‘#17BECF
DECREASING_COLOR = ‘#7F7F7F
BACKYEAR=7
WINDOW_SIZE=10
NUM_OF_STD=5
today = dt.datetime.now()
dateparse = lambda x: pd.datetime.strptime(x, ‘%Y-%m-%d’)

ticker = ‘AAPL’

app.layout = html.Div([
dcc.Tabs(
id=“tabs”,
value=‘tab-1’,
#parent_className=‘custom-tabs’,
className=‘custom-tabs-container’,
children=[
dcc.Tab(
label=‘Tab one’,
value=‘tab-1’,
className=‘custom-tab’,
selected_className=‘custom-tab–selected’,
children=[
html.Div([
html.H3(‘Stock Config’),
html.Button(‘Update Stocks’, id=‘updateStockButton’),
dcc.Loading(id=“loading-stocks”, children=[html.Div(id=“loading-output-1”)], type=“default”),
html.Div(id=‘config-container’, children=‘Click to update stocks.’)
])
]
),
dcc.Tab(
label=‘Tab two’,
value=‘tab-2’,
className=‘custom-tab’,
selected_className=‘custom-tab–selected’,
children=[

            ]
        ),
    ]),
html.Div(id='tabs-content')

])

@app.callback(Output(‘config-container’, ‘children’),
[Input(‘updateStockButton’, ‘n_clicks’)])
def download_stocks(n_clicks):
start = dt.datetime(today.year-BACKYEAR, 1, 1)
df_quote = web.DataReader(ticker, ‘yahoo’, start, today)
df_quote.to_csv(default_path+’\data\’+ticker+’.csv’)
return ‘Stocks has downloaded {} times.’.format(
n_clicks
)

@app.callback(Output(“loading-output-1”, “children”),
[Input(“updateStockButton”, “n_clicks”)])
def input_triggers_spinner(n_click):
time.sleep(1)

if name == ‘main’:
app.run_server(debug=True)

Checkout the FAQ here (https://dash.plot.ly/faqs) - specifically the one titled " Q: How do I determine which Input has changed?"

It shows the dash.callback_context that is available. Inspect the output of this command to see what else it provides; I utilize various aspects at the top of many of my callbacks in order to perform certain actions based on what component triggered the callback (or return no_update to various output components if callback was triggered by reload (vice clicking on a component)

Hi flyingcujo,

Thanks for the advice. I had tried the above dash.callback_context and the callback still load the information whenever the app started. Nevertheless, i’m still trying to resolve it.

start = dt.datetime(today.year-BACKYEAR, 1, 1)
df_quote = web.DataReader(ticker, ‘yahoo’, start, today)
df_quote.to_csv(default_path+’\data\’+ticker+’.csv’)

Regards,
Alex

are you able to provide more code so I can see your callback structure? this would help provide more constructive feedback

Yes sure. Here is the full code. Thank you. When the app started, it already downloaded AAPL.csv file which is not I expecting. I expecting the file downloaded after I click on the button.

import os
import pandas_datareader.data as web
import pandas as pd
import datetime as dt
import plotly.graph_objs as go
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
import time

external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]
app = dash.Dash(name, external_stylesheets=external_stylesheets)
default_path = os.path.dirname(os.path.realpath(‘file’))

INCREASING_COLOR = ‘#17BECF
DECREASING_COLOR = ‘#7F7F7F
BACKYEAR=7
WINDOW_SIZE=10
NUM_OF_STD=5
today = dt.datetime.now()
dateparse = lambda x: pd.datetime.strptime(x, ‘%Y-%m-%d’)

ticker = ‘AAPL’

app.layout = html.Div([
dcc.Tabs(
id=“tabs”,
value=‘tab-1’,
#parent_className=‘custom-tabs’,
className=‘custom-tabs-container’,
children=[
dcc.Tab(
label=‘Tab one’,
value=‘tab-1’,
className=‘custom-tab’,
selected_className=‘custom-tab–selected’,
children=[
html.Div([
html.H3(‘Stock Config’),
dcc.Input(id=‘input-1-state’, type=‘text’, value=‘aapl’),
html.Button(‘Update Stocks’, id=‘updateStockButton’),
dcc.Loading(id=“loading-stocks”, children=[html.Div(id=“loading-output-1”)], type=“default”),
html.Div(id=‘config-container’, children=‘Click to update stocks.’)
])
]
),
dcc.Tab(
label=‘Tab two’,
value=‘tab-2’,
className=‘custom-tab’,
selected_className=‘custom-tab–selected’,
children=[

            ]
        ),
    ]),
html.Div(id='tabs-content')

])

@app.callback(Output(‘config-container’, ‘children’),
[Input(‘updateStockButton’, ‘n_clicks’)],
[State(‘input-1-state’, ‘value’)])
def download_stocks(n_clicks, input1):
if dash.callback_context.inputs.values() is None:
raise dash.exceptions.PreventUpdate
ctx = dash.callback_context

if not ctx.triggered:
    button_id = 'No clicks yet'
else:
    button_id = ctx.triggered[0]['prop_id'].split('.')[0]
    
    start = dt.datetime(today.year-BACKYEAR, 1, 1)
    df_quote = web.DataReader(ticker, 'yahoo', start, today)
    df_quote.to_csv(default_path+'\data\\'+ticker+'.csv')
return u'Stocks {} has downloaded {} , {} times.'.format(
    input1, button_id, n_clicks
)

@app.callback(Output(“loading-output-1”, “children”),
[Input(“updateStockButton”, “n_clicks”)])
def input_triggers_spinner(n_click):
time.sleep(1)

if name == ‘main’:
app.run_server(debug=True)

Not able to run the code, but it appears the if not ctx.triggered condition is not evaluating as you are expecting. I would use if ctx.triggered[0]['prop_id'].split('.')[0] == 'updateStockButton' as the conditional test to see if button was pressed. I have experienced instances in which callbacks have been triggered by components other that those listed in Inputs…if this is true in your case, then your if not ctx.triggered will evaluate to False. Hope this helps…

Thanks for the assistance and replied. I get to understand how to use callback_context.
Nevertheless i apply ctx.triggered[0][‘value’]==None to check if the button is triggered. This ticket may closed. So much thanks for your help.

you can try with this

def download_stocks(n_clicks,input1):
    if n_clicks>0:
        rest of the code

Have you the solution for this problem? I have the same issue , Could you help me?

You can just rely on the following dash trick. here is the sample code.

ctx = dash.callback_context
if not ctx.triggered:
trigger_id = ‘Noclicksyet’
else:
if trigger_id in ["<object1(for example click object>", “object2”,“object3”]:
raise dash.exceptions.PreventUpdate

I’ve used in my dash apps several time. it works very well.
enjoy.
Tony