Python+Dash快速web应用开发:回调交互篇(上)

简介: Python+Dash快速web应用开发:回调交互篇(上)

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应用需要做什么:

  • 「确定输入与输出部件」

一个可交互的系统一定是有「输入」「输出」的,我们开头导入的InputOutput对象,他们分别扮演着「输入者」「输出者」两种角色,其各自的第一个参数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,之后每次等我们输入完单词,主动去点击按钮从而增加其被点击次数记录时,回调函数才会被触发,这样就方便了我们的很多复杂应用场景~

目录
相关文章
|
1月前
|
API C++ 开发者
PySide vs PyQt:Python GUI开发史诗级对决,谁才是王者?
PySide 和 PyQt 是 Python GUI 开发领域的两大利器,各有特色。PySide 采用 LGPL 协议,更灵活;PyQt 默认 GPL,商业使用需授权。两者背后团队实力雄厚,PySide 得到 Qt 官方支持,PyQt 由 Riverbank Computing 打造。API 设计上,PySide 简洁直观,贴近原生 Qt;PyQt 增加 Pythonic 接口,操作更高效。性能方面,两者表现优异,适合不同需求的项目开发。选择时可根据项目特点与开源要求决定。
111 20
|
2月前
|
程序员 测试技术 开发工具
怎么开发Python第三方库?手把手教你参与开源项目!
大家好,我是程序员晚枫。本文将分享如何开发Python第三方库,并以我维护的开源项目 **popdf** 为例,指导参与开源贡献。Popdf是一个PDF操作库,支持PDF转Word、转图片、合并与加密等功能。文章涵盖从fork项目、本地开发、单元测试到提交PR的全流程,适合想了解开源贡献的开发者。欢迎访问[popdf](https://gitcode.com/python4office/popdf),一起交流学习!
140 21
怎么开发Python第三方库?手把手教你参与开源项目!
|
2月前
|
数据采集 人工智能 测试技术
Python有哪些好用且实用的Web框架?
Python 是一门功能强大的编程语言,在多个领域中得到广泛应用,包括爬虫、人工智能、游戏开发、自动化测试和 Web 开发。在 Web 开发中,Python 提供了多种框架以提高效率。以下是几个常用的 Python Web 框架:1) Django:开源框架,支持多种数据库引擎,适合新手;2) Flask:轻量级框架,基于简单核心并通过扩展增加功能;3) Web2py:免费开源框架,支持快速开发;4) Tornado:同时作为 Web 服务器和框架,适合高并发场景;5) CherryPy:简单易用的框架,连接 Web 服务器与 Python 代码。这些框架各有特色,可根据需求选择合适的工具。
119 14
|
2月前
|
JavaScript 前端开发 关系型数据库
基于Python+Vue开发的体育场馆预约管理系统源码+运行
本项目为大学生课程设计作业,采用Python和Vue技术构建了一个体育场馆预约管理系统(实现前后端分离)。系统的主要目标在于帮助学生理解和掌握Python编程知识,同时培养其项目规划和开发能力。参与该项目的学习过程,学生能够在实际操作中锻炼技能,为未来的职业发展奠定良好的基础。
100 3
|
2月前
|
前端开发 JavaScript 关系型数据库
基于Python+Vue开发的房产销售管理系统源码+运行
基于Python+Vue开发的房产销售管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Python编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Python的房产销售管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
64 2
|
27天前
|
Web App开发 前端开发 JavaScript
鸿蒙5开发宝藏案例分享---Web适配一多开发实践
这是一份实用的鸿蒙Web多设备适配开发指南,针对开发者在不同屏幕尺寸下的布局难题提供了解决方案。文章通过三大法宝(相对单位、媒体查询和窗口监听)详细介绍如何实现智能适配,并提供了多个实战案例,如宫格布局、对话框变形和自适应轮播图等。此外,还分享了调试技巧及工具推荐,帮助开发者快速上手并优化性能。最后鼓励读者实践探索,并提示更多官方资源等待发现。
|
3月前
|
关系型数据库 MySQL 数据库
基于Flink CDC 开发,支持Web-UI的实时KingBase 连接器,三大模式无缝切换,效率翻倍!
TIS 是一款基于Web-UI的开源大数据集成工具,通过与人大金仓Kingbase的深度整合,提供高效、灵活的实时数据集成方案。它支持增量数据监听和实时写入,兼容MySQL、PostgreSQL和Oracle模式,无需编写复杂脚本,操作简单直观,特别适合非专业开发人员使用。TIS率先实现了Kingbase CDC连接器的整合,成为业界首个开箱即用的Kingbase CDC数据同步解决方案,助力企业数字化转型。
549 5
基于Flink CDC 开发,支持Web-UI的实时KingBase 连接器,三大模式无缝切换,效率翻倍!
|
8月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
465 3
|
3月前
|
机器学习/深度学习 开发框架 API
Python 高级编程与实战:深入理解 Web 开发与 API 设计
在前几篇文章中,我们探讨了 Python 的基础语法、面向对象编程、函数式编程、元编程、性能优化、调试技巧以及数据科学和机器学习。本文将深入探讨 Python 在 Web 开发和 API 设计中的应用,并通过实战项目帮助你掌握这些技术。
|
7月前
|
存储 前端开发 JavaScript
如何在项目中高效地进行 Web 组件化开发
高效地进行 Web 组件化开发需要从多个方面入手,通过明确目标、合理规划、规范开发、加强测试等一系列措施,实现组件的高效管理和利用,从而提高项目的整体开发效率和质量,为用户提供更好的体验。
186 63

推荐镜像

更多