Callbacks专题
继初体验之后,这一部分是对应tutorial之后的回调专题。
高级特性
1.控制回调不更新-1
从doc中摘抄一句Callback functions: Python functions that are automatically called by Dash whenever an input component‘s property changes.
那如果想在特定的情况不进行更新,使用:from dash.exceptions import PreventUpdate
import dash
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css‘]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.Button(‘Click here to see the content‘, id=‘show-secret‘),
html.Div(id=‘body-div‘)
])
@app.callback(
Output(component_id=‘body-div‘, component_property=‘children‘),
Input(component_id=‘show-secret‘, component_property=‘n_clicks‘)
)
def update_output(n_clicks):
if (n_clicks is None) or (n_clicks % 2 == 0): # 未点击或偶数不更新内容
raise PreventUpdate
else:
return "So the n_clicks now is: {}.".format(str(n_clicks))
if __name__ == ‘__main__‘:
app.run_server(debug=True)
得到:
初始时raise PreventUpdate,后续每次按键被点击次数到偶数次时,内容不更新。
2.控制回调不更新-2
在无需更新的output位置返回dash.no_update
即可。
3.回调上下文信息
作用域为回调函数内部,通过dash.callback_context
获取包含Input、State和Trigger信息记录,返回Json格式数据。
ctx = dash.callback_context
ctx_msg = json.dumps({
‘states‘: ctx.states, # 这个看到的基本都是空
‘triggered‘: ctx.triggered, # 最近一次的触发信息
‘inputs‘: ctx.inputs # 历史输入信息记录
}, indent=2)
4.revent_initial_call
参数
先上官网Demo
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
app = dash.Dash(__name__, suppress_callback_exceptions=True)
app.layout = html.Div([
dcc.Location(id=‘url‘),
html.Div(id=‘layout-div‘),
html.Div(id=‘content‘)
])
@app.callback(Output(‘content‘, ‘children‘), Input(‘url‘, ‘pathname‘))
def display_page(pathname):
return html.Div([
dcc.Input(id=‘input‘, value=‘hello world‘),
html.Div(id=‘output‘)
], style={‘background-color‘: ‘red‘}
)
@app.callback(Output(‘output‘, ‘children‘), Input(‘input‘, ‘value‘), prevent_initial_call=True)
def update_output(value):
print(‘>>> update_output‘)
return value
@app.callback(Output(‘layout-div‘, ‘children‘), Input(‘input‘, ‘value‘), prevent_initial_call=True)
def update_layout_div(value):
print(‘>>> update_layout_div‘)
return value
if __name__ == ‘__main__‘:
app.run_server(debug=True)
得到:
上面这个是初始时进入界面看到的,加了个颜色便于后期自己查看变化(看来自己真的不适合前端这些设计,尴尬??)
这个Demo想说明的是:prevent_initial_call
方法在某些场合不适用。
对应到这个Demo中,可以看终端输出发现update_layout_div
回调函数的执行不受影响,每次刷新页面都会执行。
原因如下:
具体可以替换掉suppress_callback_exceptions
以及prevent_initial_call
观察异常情况。
在这个demo中,app初始化时传递suppress_callback_exceptions=True
是给禁止初始回调的函数假定一个输入input,若是去掉便会报错找不到id=input.
5.循环回调
体验一下官网Demo就能体会到 页面A组件与B组件之间相互作为输入输出同步更新 这一用法,在这里传入的属性是value
.
写在后面,其实看到这里,就有些不想暂时把这个当作短期继续更新的方向了,更多的是前端的东西让我不习惯。
想到早期用Flask/Django弄的一些丑丑的Demo,笨拙,不堪回首。。。
2021.7.27 Dash部分先行停更(实际作图过程中,Tableau/PowerBI、有数BI、Python其他绘图库、Excel/PPT 足够)
参考资源
官网Advanced Callbacks章节