Dash 2.9.0版本重磅新功能一览 - 费弗里
source link: https://www.cnblogs.com/feffery/p/17227380.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
本文示例代码已上传至我的
Github
仓库https://github.com/CNFeffery/dash-master
大家好我是费老师,就在昨晚,Dash
框架发布了其2.9.0版本更新,在一众更新内容中,有两条新特性在我看来尤为重要,可以大幅度提升我们开发Dash
应用的效率,下面我就将带大家一起了解它们的具体内容:
1 允许多个回调函数重复Output#
在之前版本的Dash
中,严格限制了不同的回调函数不可以对相同的id.属性
目标进行输出,以下面的示例应用为例:
import dash
from dash import html
import feffery_antd_components as fac
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.layout = html.Div(
[
fac.AntdSpace(
[
fac.AntdButton(
'按钮1',
id='button-demo1'
),
fac.AntdButton(
'按钮2',
id='button-demo2'
)
]
),
fac.AntdParagraph(
id='output-demo'
)
],
style={
'padding': '50px 100px'
}
)
@app.callback(
Output('output-demo', 'children'),
Input('button-demo1', 'nClicks'),
prevent_initial_call=True
)
def trigger1(nClicks):
return f'按钮1: {nClicks}'
@app.callback(
Output('output-demo', 'children'),
Input('button-demo2', 'nClicks'),
prevent_initial_call=True
)
def trigger2(nClicks):
return f'按钮2: {nClicks}'
if __name__ == '__main__':
app.run(debug=True)
如果我们希望两个AntdButton
分别点击后,可以通过两个不同的回调函数对同一AntdPargraph
的内容进行输出,在之前的版本中默认会报下图所示的Duplicate callback outputs
错误:
在之前的版本中遇到这种情况解决方式也有很多,常用的如将多个回调函数整合为一个并在回调函数中,再基于dash.ctx.triggered_id
判断每次回调函数究竟是由哪个Input
触发的,这在较复杂回调功能的编写中就不太方便了。
而从Dash
2.9.0版本开始,为Output()
引入了bool型新参数allow_duplicate
,默认为False
,当设置为True
后,当前Output
便可以允许通过多个回调函数共同输出,将上面的例子回调部分进行改造,对后续重复的Output
设置allow_duplicate=True
:
@app.callback(
Output('output-demo', 'children', allow_duplicate=True),
Input('button-demo2', 'nClicks'),
prevent_initial_call=True
)
def trigger2(nClicks):
return f'按钮2: {nClicks}'
就可以不受限制啦~
当然,虽然有了这个新特性帮助我们解除了不少限制,但是我的建议还是不要滥用,它不一定可以使得我们的代码更简洁,基于dash.ctx.triggered_id
的分支判断在很多场景下还是更合适。
作为一个新的功能,allow_duplicate
目前在常规的服务端回调函数中运作正常,但在浏览器端回调函数中暂时无法使用,静待后续Dash
官方的更新。
2 新增Patch()操作模式#
Dash
2.9.0版本中新增参数局部快捷更新操作Patch()
,使得我们可以在回调函数中对目标属性进行局部更新,这样说起来还是比较抽象,我们举例说明:
假如我们的应用中要实现这样的交互逻辑:每点击一次AntdButton
,就会在下方AntdSpace
中新增一行文字内容,在以前的版本中,要实现这个功能,我们需要在回调函数中额外将目标AntdSpace
的children
属性作为State
传入,从而在每次回调执行时,将新的一行内容追加到先前状态的children
列表中,再进行输出:
import dash
import uuid
from dash import html
import feffery_antd_components as fac
from dash.dependencies import Input, Output, State
app = dash.Dash(__name__)
app.layout = html.Div(
[
fac.AntdButton(
'新增一行',
id='add-new-line'
),
fac.AntdSpace(
[],
id='target-container',
direction='vertical',
style={
'width': '100%'
}
)
],
style={
'padding': '50px 100px'
}
)
@app.callback(
Output('target-container', 'children'),
Input('add-new-line', 'nClicks'),
State('target-container', 'children'),
prevent_initial_call=True
)
def add_new_line(nClicks, origin_children):
return [
*origin_children,
str(uuid.uuid4())
]
if __name__ == '__main__':
app.run(debug=True)
这样做的弊端很明显——我们每次更新都需要先取回目标属性的现有状态,这带来了多余的资源消耗,而有了Patch()
模式,我们就可以将回调函数改写为下面的形式,实现相同的效果:
@app.callback(
Output('target-container', 'children'),
Input('add-new-line', 'nClicks'),
prevent_initial_call=True
)
def add_new_line(nClicks):
patch = dash.Patch()
patch.append(str(uuid.uuid4()))
return patch
相当于在回调函数中通过实例化Patch
,创建了针对目标Output
的远程代理对象,在回调函数中针对该代理对象的各种常用操作,都会在回调函数执行后落实到用户浏览器中的目标属性上,这听起来可能有些抽象,我用下面的例子展示了基于Patch
可以实现的常用局部值操作(对应代码受篇幅限制,请在文章开头的github
仓库中查看):
以上就是本文的全部内容,对Dash
应用开发感兴趣的朋友,欢迎添加微信号CNFeffery
,备注“dash学习”加入我的技术交流群,一起成长一起进步。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK