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

  上面这个应用中,体现出的模式匹配内容即为开头从dash.dependencies引入的ALL,它是Dash模式匹配中的一种模式,而我们在回调函数update_account_records()中为已有记账记录追加新纪录时,使用到:

# 以字典形式定义id id={'type': 'single-account_record', 'index': children.__len__()}

  这里不同于以前我们采取的id=某个字符串的定义方法,换成字典之后,其type键值对用来记录唯一id信息,每一次新纪录追加时type值都相等,因为它们被组织为同id部件集合,而键值对index则用于在type值相同的一个部件集合下,区分出不同的独立部件元素。

  因为将传统的唯一id部件替换成同id部件集合,所以我们后面的回调函数refresh_account_sum()的输入元素只需要定义单个Input()即可,再在函数内部按照不同的index值取出需要的集合内各成员记录值,非常便于我们书写出简练清爽的Dash代码,便于之后进一步的修改与重构。

  你可以通过最下面打印出的每次refresh_account_sum()所接收到的children参数json格式结果来弄清我是如何在return值的地方取出历史记账金额并计算的。

  而除了上面介绍的一股脑返回所有集合内成员部件的ALL模式之外,还有另一种更有针对性的MATCH模式,它应用于结合内成员部件可交互输入值的情况,譬如下面这个简单的例子,我们定义一个简单的用于查询省份行政代码的应用,配合MATCH模式来实现彼此成对独立输出:

app3.py

import dash import dash_bootstrap_components as dbc import dash_html_components as html from dash.dependencies import Input, Output, State, MATCH import dash_core_components as dcc app = dash.Dash(__name__) app.layout = html.Div( [ html.Br(), html.Br(), html.Br(), dbc.Container( [ dbc.Row( dbc.Col( dbc.Button('新增查询',, outline=True) ) ), html.Hr() ] ), dbc.Container([],) ] ) region2code = { '北京市': '110000000000', '重庆市': '500000000000', '安徽省': '340000000000' } @app.callback( Output('query-container', 'children'), Input('add-item', 'n_clicks'), State('query-container', 'children'), prevent_initial_call=True ) def add_query_item(n_clicks, children): children.append( dbc.Row( [ dbc.Col( [ # 生成index相同的dropdown部件与文字输出部件 dcc.Dropdown(id={'type': 'select-province', 'index': children.__len__()}, options=[{'label': label, 'value': label} for label in region2code.keys()], placeholder='选择省份:'), html.P('请输入要查询的省份!', id={'type': 'code-output', 'index': children.__len__()}) ] ) ] ) ) return children @app.callback( Output({'type': 'code-output', 'index': MATCH}, 'children'), Input({'type': 'select-province', 'index': MATCH}, 'value') ) def refresh_code_output(value): if value: return region2code[value] else: return dash.no_update if __name__ == '__main__': app.run_server(debug=True)

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

图4

  可以看到,在refresh_code_output()前应用MATCH模式匹配后,我们点击某个部件时,只有跟它index匹配的部件才会打印出相对应的输出,非常的方便~

2.3 多输入情况下获取部件触发情况

  在很多应用场景下,我们的某个回调可能拥有多个Input输入,但学过前面的内容我们已经清楚,不管有几个Input,只要其中有一个部件其输入属性发生变化,都会触发本轮回调,但是如果我们就想知道究竟是哪个Input触发了本轮回调该怎么办呢?

  这在Dash中可以通过dash.callback_context来方便的实现,它只能在回调函数中被执行,从而获取回调过程的诸多上下文信息,先从下面这个简单的例子出发看看dash.callback_context到底给我们带来了哪些有价值的信息:

app4.py

import dash import dash_html_components as html import dash_bootstrap_components as dbc from dash.dependencies import Input, Output import json app = dash.Dash(__name__) app.layout = html.Div( dbc.Container( [ html.Br(), html.Br(), html.Br(), dbc.Row( [ dbc.Col(dbc.Button('A',, n_clicks=0)), dbc.Col(dbc.Button('B',, n_clicks=0)), dbc.Col(dbc.Button('C',, n_clicks=0)) ] ), dbc.Row( [ dbc.Col(html.P('按钮A未点击',)), dbc.Col(html.P('按钮B未点击',)), dbc.Col(html.P('按钮C未点击',)) ] ), dbc.Row( dbc.Col( html.Pre(id='raw-json') ) ) ] ) ) @app.callback( [Output('A-output', 'children'), Output('B-output', 'children'), Output('C-output', 'children'), Output('raw-json', 'children')], [Input('A', 'n_clicks'), Input('B', 'n_clicks'), Input('C', 'n_clicks')], prevent_initial_call=True ) def refresh_output(A_n_clicks, B_n_clicks, C_n_clicks): # 获取本轮回调状态下的上下文信息 ctx = dash.callback_context # 取出对应State、最近一次触发部件以及Input信息 ctx_msg = json.dumps({ 'states': ctx.states, 'triggered': ctx.triggered, 'inputs': ctx.inputs }, indent=2) return A_n_clicks, B_n_clicks, C_n_clicks, ctx_msg if __name__ == '__main__': app.run_server(debug=True)

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

图5

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

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