(数据科学学习手札104)Python+Dash快速web应用开发——回调交互篇(上)
本文示例代码已上传至我的
Github仓库https://github.com/CNFeffery/DataScienceStudyNotes
1 简介
这是我的系列教程Python+Dash快速web应用开发的第三期,在前两期的教程中,我们围绕什么是Dash,以及如何配合方便好用的第三方拓展dash-bootstrap-components来为我们的Dash应用设计布局展开了非常详细的介绍。
而Dash最吸引我的地方在于其高度封装了react.js,使得我们无需编写js语句,纯Python编程就可以实现浏览器前端与后端计算之间常规的异步通信,从而创造出功能强大的交互式web应用。
图1
从今天的文章开始,我就将开始带大家走进Dash的核心内容——回调。
2 Dash中的基础回调
2.1 最基础的回调
Dash中的回调(callback)是以装饰器的形式,配合自编回调函数,实现前后端异步通信交互,这句话可能不太好理解,我们从一个简单的例子出发来认识Dash中的回调:
app1.py
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
app = dash.Dash(
__name__,
external_stylesheets=['css/bootstrap.min.css']
)
app.layout = html.Div(
[
html.Br(),
html.Br(),
html.Br(),
dbc.Container(
[
dbc.Row(
[
dbc.Col(dbc.Input(id='input-value',
placeholder='请输入些东西'),
width=12),
dbc.Col(dbc.Label(id='output-value'),
width=12)
]
)
]
)
]
)
# 对应app实例的回调函数装饰器
@app.callback(
Output('output-value', 'children'),
Input('input-value', 'value')
)
def input_to_output(input_value):
'''
简单的回调函数
'''
return input_value
if __name__ == '__main__':
app.run_server()
先来看看app1的交互效果:
图2
下面我们来分解上面的代码,梳理一下要构造一个具有实际交互功能的Dash应用需要做什么:
- 确定输入与输出部件
一个可交互的系统一定是有输入与输出的,我们开头导入的Input与Output对象,他们分别扮演着输入者与输出者两种角色,其各自的第一个参数component_id用于联动前端部分定义的部件。
我们在前面定义前端部件时,为dbc.Input对应的输入框设置了id='input-value',为dbc.Label对应的文字输出设置了id='output-value',让它们作为第一个参数可以被Input()与Output()唯一识别出来。
- 确定输入与输出内容
在确定了输入者与输出者之后,更重要的是为告诉Dash需要监听什么输入,响应什么输出,这就要用到第二个参数component_property。
它与对应的前端部件有关,譬如我们的dbc.Input()输入框,其被输入的内容都存在value属性中,而children属性是dbc.Label以及绝大多数html部件的第一个参数,这样我们就确定了输入输出内容。
- 装饰回调函数
app.callback()装饰器按照规定的先Output()后Input()的顺序传入相应对象,而既然是装饰器,自然需要配合自定义回调函数使用。
我们的input_to_output()就是对应的回调函数,其参数与装饰器中的Input()对应,而函数内部则用来定义计算处理过程。
最后return的对象则对应Output()。
# 对应app实例的回调函数装饰器
@app.callback(
Output('output-value', 'children'),
Input('input-value', 'value')
)
def input_to_output(input_value):
'''
简单的回调函数
'''
return input_value
通过上面这样的结构,我们得以纯Python“寥寥数语”实现了交互功能,赋予我们编写任意功能Dash应用的能力。
2.2 同时设置多个Input()与Output()
在上一小节中我们介绍的是最基本的单输入 -> 单输出回调模式,很多时候我们需要更复杂的回调模式,譬如下面的例子:
app2.py
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
app = dash.Dash(
__name__,
external_stylesheets=['css/bootstrap.min.css']
)
app.layout = html.Div(
[
html.Br(),
html.Br(),
html.Br(),
dbc.Container(
[
dbc.Row(
[
dbc.Col(dbc.Input(id='input-value1'), width=3),
dbc.Col(html.P('+'), width=1),
dbc.Col(dbc.Input(id='input-value2'), width=3),
],
justify='start'
),
html.Hr(),
dbc.Label(id='output-value')
]
)
]
)
@app.callback(
Output('output-value', 'children'),
Input('input-value1', 'value'),
Input('input-value2', 'value')
)
def input_to_output(input_value1, input_value2):
try:
return float(input_value1) + float(input_value2)
except:
return '请输入合法参数!'
if __name__ == '__main__':
app.run_server()
图3
这里我们的Input()对象不止一个,在Output()对象之后依次传入(也可以把所有Input()对象包在一个列表中传入),其顺序对应后面回调函数的参数顺序,从而实现了多个输入值的一一对应。
同样的,Output()也可以有多个:
app3.py
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
app = dash.Dash(
__name__,
external_stylesheets=['css/bootstrap.min.css']
)
app.layout = html.Div(
[
html.Br(),
html.Br(),
html.Br(),
dbc.Container(
[
dbc.Row(
[
dbc.Col(dbc.Input(id='input-lastname'), width=3),
dbc.Col(html.P('+'), width=1),
dbc.Col(dbc.Input(id='input-firstname'), width=3),
],
justify='start'
),
html.Hr(),
dbc.Label(id='output1'),
html.Br(),
dbc.Label(id='output2')
]
)
]
)
@app.callback(
[Output('output1', 'children'),
Output('output2', 'children')],
[Input('input-lastname', 'value'),
Input('input-firstname', 'value')]
)
def input_to_output(lastname, firstname):
try:
return '完整姓名:' + lastname + firstname, f'姓名长度为{len(lastname+firstname)}'
except:
return '等待输入...', '等待输入...'
if __name__ == '__main__':
app.run_server()
图4
可以看到不管是多个Output()还是Input(),只需要嵌套在列表中即可。
2.3 利用State()实现惰性交互
很多情况下,如果我们的回调函数计算过程时间开销较大,那么像前面介绍的仅靠Input()与Output()实现的前后端通信会很频繁,因为监听到的所有输入部件对应属性值只要略一改变,就会触发回调。
为了解决这类问题,Dash中设计了State()对象,我们可以利用State()替换Input()来绑定对应的输入值,再将一些需要主动触发的譬如dbc.Button()按钮部件的属性n_clicks,作为Input()对象进行绑定。
让我们通过下面的例子更好的理解它的作用:
app4.py
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
app = dash.Dash(
__name__,
external_stylesheets=['css/bootstrap.min.css']
)
app.layout = html.Div(
[
html.Br(),
html.Br(),
html.Br(),
dbc.Container(
[
dbc.Row(
[
dbc.Col(dbc.Input(id='input-value'),
width=4),
dbc.Col(dbc.Button('小写转大写',
id='state-button',
n_clicks=0),
width=4),
dbc.Col(dbc.Label(id='output-value',
style={'padding': '0',
'margin': '0',
'line-height': '38px'}),
width=4)
],
justify='start'
)
]
)
]
)
@app.callback(
Output('output-value', 'children'),
Input('state-button', 'n_clicks'),
State('input-value', 'value')
)
def input_to_output(n_clicks, value):
if n_clicks:
return value.upper()
if __name__ == '__main__':
app.run_server()
图5
可以看到,装饰器中按照Output()、Input()、State()的顺序传入各个对象后,我们的Button()部件的n_clicks参数记录了对应的按钮被点击了多少次,初始化我们设置其为0,之后每次等我们输入完单词,主动去点击按钮从而增加其被点击次数记录时,回调函数才会被触发,这样就方便了我们的很多复杂应用场景~
以上就是本期的全部内容,欢迎在评论区与我进行讨论~
(数据科学学习手札104)Python+Dash快速web应用开发——回调交互篇(上)的更多相关文章
- (数据科学学习手札105)Python+Dash快速web应用开发——回调交互篇(中)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札106)Python+Dash快速web应用开发——回调交互篇(下)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札102)Python+Dash快速web应用开发——基础概念篇
本文示例代码与数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的新系列教程Python+Dash快 ...
- (数据科学学习手札108)Python+Dash快速web应用开发——静态部件篇(上)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札109)Python+Dash快速web应用开发——静态部件篇(中)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札118)Python+Dash快速web应用开发——特殊部件篇
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札103)Python+Dash快速web应用开发——页面布局篇
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札110)Python+Dash快速web应用开发——静态部件篇(下)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札123)Python+Dash快速web应用开发——部署发布篇
1 简介 这是我的系列教程Python+Dash快速web应用开发的第二十期,在上一期中我介绍了利用内网穿透的方式,将任何可以联网的电脑作为"服务器"向外临时发布你的Dash应用. ...
随机推荐
- 移动端 CSS3动画属性
一.transform 转换属性 #1. translate位移 transform : translate(50px,100px); //把元素水平移动 50 像素,垂直移动 100 像素 tran ...
- DP-DAY3游记
问题 A: 2017夏令营第一阶段(Day3)问题A拆分数字I 题目描述 把数字N拆分一些正整数的和,问有多少种不同的方法? 例如:N=4,有1+1+1+1.1+1+2.1+2+1.1+3.2+ ...
- Flink 反压 浅入浅出
前言 微信搜[Java3y]关注这个朴实无华的男人,点赞关注是对我最大的支持! 文本已收录至我的GitHub:https://github.com/ZhongFuCheng3y/3y,有300多篇原创 ...
- [译] 使用 Espresso 隔离测试视图
原文地址:Testing Views in Isolation with Espresso 原文作者:Ataul Munim 译文出自:掘金翻译计划 译者:yazhi1992 校对者:lovexiao ...
- [leetcode]114. Flatten Binary Tree to Linked List由二叉树构建链表
/* 先序遍历构建链表,重新构建树 */ LinkedList<Integer> list = new LinkedList<>(); public void flatten( ...
- 【C】C语言位域(位段)详解
作者:李春港 出处:https://www.cnblogs.com/lcgbk/p/14215449.html 目录 一.位域是什么? 二.位域的存储 2.1 相邻成员的类型相同 2.2 相邻成员的类 ...
- 浅析pagehelper分页原理
原文链接 https://blog.csdn.net/qq_21996541/article/details/79796117 之前项目一直使用的是普元框架,最近公司项目搭建了新框架,主要是由公司的大 ...
- spark:reducebykey与groupbykey的区别
从源码看: reduceBykey与groupbykey: 都调用函数combineByKeyWithClassTag[V]((v: V) => v, func, func, partition ...
- windows7 错误0xc00000ba;无法进入系统;
事件背景:电脑windows7 错误0xc00000ba无法进系统:无法进入安全模式:无法进入最后一次正确配置: 事件处理:提示系统文件丢失,注册表异常:知乎有人提及更换WS2_32.DLL; 使用P ...
- springboot源码解析-管中窥豹系列之项目类型(二)
一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...