(数据科学学习手札106)Python+Dash快速web应用开发——回调交互篇(下)

   这是我的系列教程Python+Dash快速web应用开发的第五期,在上一期的文章中,我们针对Dash中有关回调的一些技巧性的特性进行了介绍,使得我们可以更愉快地为Dash应用编写回调交互功能。

  而今天的文章作为回调交互系统性内容的最后一期,我将带大家get一些Dash中实际应用效果惊人的高级回调特性,系好安全带,我们起飞~

(数据科学学习手札106)Python+Dash快速web应用开发——回调交互篇(下)

图1 2 Dash中的高级回调特性 2.1 控制部分回调输出不更新

  在很多应用场景下,我们给某个回调函数绑定了多个Output(),这时如果这些Output()并不是每次触发回调都需要被更新,那么就可以根据Input()值的不同,来配合dash.no_update作为对应Output()的返回值,从而实现部分Output()不更新,譬如下面的例子:

app1.py

import dash import dash_bootstrap_components as dbc import dash_html_components as html from dash.dependencies import Input, Output import time app = dash.Dash(__name__) app.layout = html.Div( dbc.Container( [ html.Br(), html.Br(), html.Br(), dbc.Row( dbc.Col( dbc.Button('按钮', color='primary',, n_clicks=0) ) ), html.Br(), dbc.Row( [ dbc.Col('尚未触发',), dbc.Col('尚未触发',), dbc.Col('尚未触发',) ] ) ] ) ) @app.callback( [Output('record-1', 'children'), Output('record-2', 'children'), Output('record-n', 'children'), ], Input('button', 'n_clicks'), prevent_initial_call=True ) def record_click_event(n_clicks): if n_clicks == 1: return ( '第1次点击:{}'.format(time.strftime('%H:%M:%S', time.localtime(time.time()))), dash.no_update, dash.no_update ) elif n_clicks == 2: return ( dash.no_update, '第2次点击:{}'.format(time.strftime('%H:%M:%S', time.localtime(time.time()))), dash.no_update ) elif n_clicks >= 3: return ( dash.no_update, dash.no_update, '第3次及以上点击:{}'.format(time.strftime('%H:%M:%S', time.localtime(time.time()))), ) if __name__ == '__main__': app.run_server(debug=True)

(数据科学学习手札106)Python+Dash快速web应用开发——回调交互篇(下)

图2

  可以观察到,我们根据n_clicks数值的不同,在对应各个Output()返回值中对符合条件的部件进行更新,其他的都用dash.no_update来代替,从而实现了局部更新,非常实用且简单。

2.2 基于模式匹配的回调

  这是Dash在1.11.0版本开始引入的新特性,它所实现的功能是将多个部件绑定组织在同一个id属性下,这听起来有一点抽象,我们先从一个形象的例子来出发:

  假如我们要开发一个简单的记账应用,它通过第一排若干Input()部件及一个Button()部件来记录并提交每笔账对应的相关信息,并且在最下方输出已记录账目金额之和:

app2.py

import dash import dash_bootstrap_components as dbc import dash_core_components as dcc import dash_html_components as html from dash.dependencies import Input, Output, State, ALL import re app = dash.Dash(__name__) app.layout = html.Div( [ html.Br(), html.Br(), dbc.Container( dbc.Row( [ dbc.Col( dbc.InputGroup( [ dbc.InputGroupAddon("金额", addon_type="prepend"), dbc.Input(, placeholder='请输入金额', type="number", ), dbc.InputGroupAddon("元", addon_type="append"), ], ), width=5 ), dbc.Col( dcc.Dropdown(, options=[ {'label': '生活开销', 'value': '生活开销'}, {'label': '人情往来', 'value': '人情往来'}, {'label': '医疗保健', 'value': '医疗保健'}, {'label': '旅游休闲', 'value': '旅游休闲'}, ], placeholder='请选择类型:' ), width=5 ), dbc.Col( dbc.Button('提交记录',), width=2 ) ] ) ), html.Br(), dbc.Container([],), dbc.Container('暂无记录!',) ] ) @app.callback( Output('account-record-container', 'children'), Input('account-submit', 'n_clicks'), [State('account-record-container', 'children'), State('account-amount', 'value'), State('account-type', 'value')], prevent_initial_call=True ) def update_account_records(n_clicks, children, account_amount, account_type): ''' 用于处理每一次的记账输入并渲染前端记录 ''' if account_amount and account_type: children.append(dbc.Row( dbc.Col( '【{}】类开销【{}】元'.format(account_type, account_amount) ), # 以字典形式定义id id={'type': 'single-account_record', 'index': children.__len__()} )) return children @app.callback( Output('account-record-sum', 'children'), Input({'type': 'single-account_record', 'index': ALL}, 'children'), prevent_initial_call=True ) def refresh_account_sum(children): ''' 对多部件集合single-account_record下所有账目记录进行求和 ''' return '账本总开销:{}'.format(sum([int(re.findall('\d+', child['props']['children'])[0]) for child in children])) if __name__ == '__main__': app.run_server(debug=True)

(数据科学学习手札106)Python+Dash快速web应用开发——回调交互篇(下)

图3

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpygpp.html