本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes

1 简介

   这是我的系列教程Python+Dash快速web应用开发的第十三期,在上一期中,我们一起认识了Dash自带的交互式表格组件dash_table,并学会了如何自定义表格中不同部分的样式。

  而今天的教程,我们将继续深入认识dash_table的更多交互方面的功能,学习如何为渲染出的表格分页,并添加动态内容修改等交互功能。

图1

2 dash_table的基础交互能力

  dash_table的核心功能是赋予用户与图表进行快捷交互的能力,下面我们来学习其基础常用的一些交互功能:

2.1 分页翻页

  当我们要展示的数据行数较多时,在网页中渲染可以选择分页,这在dash_table中实现起来比较方便,根据数据传递方式的不同,可以分为前端分页后端分页

2.1.1 前端分页

  前端分页顾名思义,就是在我们访问Dash应用时,表格内所有页面的数据一次性加载完成,适合数据量不大的情况,将数据存储压力置转移到浏览器端。

  通过参数page_size设置每页要显示的记录行数,Dash会自动帮我们分好页,并配上翻页部件:

app1.py

import dash
import dash_bootstrap_components as dbc
import dash_table import seaborn as sns df = sns.load_dataset('tips')
df.insert(0, '#', df.index) app = dash.Dash(__name__) app.layout = dbc.Container(
[
dash_table.DataTable(
id='dash-table',
data=df.to_dict('records'),
columns=[
{'name': column, 'id': column}
for column in df.columns
],
page_size=15, # 设置单页显示15行记录行数
style_header={
'font-family': 'Times New Romer',
'font-weight': 'bold',
'text-align': 'center'
},
style_data={
'font-family': 'Times New Romer',
'text-align': 'center'
}
)
],
style={
'margin-top': '50px'
}
) if __name__ == '__main__':
app.run_server(debug=True)

图2

  ### 2.1.2 后端分页

  虽然前端分页简单易用,但当我们的数据很大时,强行使用前端分页会给网络传输浏览器端带来不小的延迟和内存压力,严重影响用户体验,因此Dash贴心地为我们准备了后端分页方式。

  这时首先我们得为DataTable设置参数page_action='custom',这是使用后端分页的先决条件,接下来我们需要认识一些新的参数:

  page_current,int型,对应当前翻到的页码;

  page_count,int型,对应显示的总页数;

  我们在使用后端分页时,实际上就是通过用户当前翻到的页码,以及设定的page_size,来动态地在翻页后加载对应批次的数据,并控制显示的总页数,参考下面这个简单的例子:

app2.py

import dash
import dash_bootstrap_components as dbc
import dash_table
from dash.dependencies import Input, Output import seaborn as sns
import pandas as pd
from tqdm import tqdm # 压力测试
df = pd.concat([sns.load_dataset('tips') for _ in tqdm(range(1000))], ignore_index=True)
df.insert(0, '#', df.index) app = dash.Dash(__name__) app.layout = dbc.Container(
[
dbc.Spinner(
dash_table.DataTable(
id='dash-table',
columns=[
{'name': column, 'id': column}
for column in df.columns
],
page_size=15, # 设置单页显示15行记录行数
page_action='custom',
page_current=0,
style_header={
'font-family': 'Times New Romer',
'font-weight': 'bold',
'text-align': 'center'
},
style_data={
'font-family': 'Times New Romer',
'text-align': 'center'
}
)
)
],
style={
'margin-top': '50px'
}
) @app.callback(
[Output('dash-table', 'data'),
Output('dash-table', 'page_count')],
[Input('dash-table', 'page_current'),
Input('dash-table', 'page_size')]
)
def refresh_page_data(page_current, page_size):
return df.iloc[page_current * page_size:(page_current + 1) * page_size].to_dict('records'), 1 + df.shape[
0] // page_size if __name__ == '__main__':
app.run_server(debug=True)

  可以看到,即使我们完整的数据集被我concat到24万行,加载应用以及网页内翻页时依然轻松自如毫无压力,在实际应用中你还可以将翻页部分改成受到LIMITOFFSET控制的数据库查询过程,使得应用运行的更加快速高效:

图3

2.2 对单元格内容进行编辑

  讲完了分页翻页,接下来我们来学习dash_table中更加强大的功能——单元格内容编辑。

  一个现代化的web应用当然不能局限于仅仅查看数据这么简单,Dash同样赋予了我们双击数据表单元格进行数据编辑的能力,首先得设置参数editable=True,即开启表格编辑模式,接下来就可以对数据区域单元格进行任意的双击选中编辑。

  不过Dash默认的单元格被选中的样式忒丑了(是粉色的你敢信),因此我们可以利用下面的参数设置方式来自定义美化:

style_data_conditional=[
{
# 对选中状态下的单元格进行自定义样式
"if": {"state": "selected"},
"background-color": "#b3e5fc",
"border": "none"
},
]

  来看一个形象的例子,我们对前端分页方式渲染出的表格进行随意的修改,并在下方对利用pandascompare比较出的数据框之间的差异结果进行打印:

app3.py

import dash
import dash_html_components as html
import dash_core_components as dcc
import dash_bootstrap_components as dbc
import dash_table
from dash.dependencies import Input, Output import seaborn as sns
import pandas as pd df = sns.load_dataset('tips')
df.insert(0, '#', df.index) app = dash.Dash(__name__) app.layout = dbc.Container(
[
dash_table.DataTable(
id='dash-table',
data=df.to_dict('records'),
columns=[
{'name': column, 'id': column}
for column in df.columns
],
fixed_rows={'headers': True},
page_size=15,
editable=True,
style_header={
'font-family': 'Times New Romer',
'font-weight': 'bold',
'text-align': 'center'
},
style_data={
'font-family': 'Times New Romer',
'text-align': 'center'
},
style_data_conditional=[
{
# 对选中状态下的单元格进行自定义样式
"if": {"state": "selected"},
"background-color": "#b3e5fc",
"border": "none"
},
]
),
html.H4('与原表格内容比较:', style={'margin-top': '50px'}),
dcc.Markdown(
'无差别',
id='markdown',
dangerously_allow_html=True
)
],
style={
'margin-top': '50px'
}
) @app.callback(
Output('markdown', 'children'),
Input('dash-table', 'data'),
prevent_initial_call=True
)
def compare_difference(dash_table_data):
print(pd.DataFrame(dash_table_data)) return df.compare(pd.DataFrame(dash_table_data)).to_html() if __name__ == '__main__':
app.run_server(debug=True)

  可以看到,我们成功地对指定单元格元素进行了修改。

图4

3 开发数据库内容在线更新工具

  在学习完今天的内容之后,我们就可以开发一个简单的,可在线自由修改并同步变动到数据库的小工具,这里我们以MySQL数据库为例,对示例表进行修改和更新:

  首先我们利用下列代码向示例数据库中新建表格tips

from sqlalchemy import create_engine
import seaborn as sns df = sns.load_dataset('tips')
df.insert(0, '#', df.index) engine = create_engine('mysql+pymysql://root:mysql@localhost/DASH') df.to_sql('tips', con=engine, if_exists='replace', index=False)

图5  

  接下来我们就以创建好的tips表为例,开发一个Dash应用,进行数据的修改和更新到数据库:

图6

  效果非常的不错,你可以在我这个简单示例的基础上,拓展更多新功能,也可以采取后端分页+条件修改的方式来应对大型数据表的修改,全部代码如下:

app4.py

import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
import dash_table
from dash.dependencies import Input, Output, State from sqlalchemy import create_engine
import pandas as pd engine = create_engine('mysql+pymysql://root:mysql@localhost/DASH') app = dash.Dash(__name__) app.layout = dbc.Container(
[
dbc.Row(
[
dbc.Col(dbc.Button('更新数据表', id='refresh-tables', style={'width': '100%'}), width=2),
dbc.Col(dcc.Dropdown(id='table-select', style={'width': '100%'}), width=2)
]
),
html.Hr(),
dash_table.DataTable(
id='dash-table',
editable=True,
page_size=15,
style_header={
'font-family': 'Times New Romer',
'font-weight': 'bold',
'text-align': 'center'
},
style_data={
'font-family': 'Times New Romer',
'text-align': 'center'
},
style_data_conditional=[
{
# 对选中状态下的单元格进行自定义样式
"if": {"state": "selected"},
"background-color": "#b3e5fc",
"border": "none"
},
]
),
dbc.Button('同步变动到数据库', id='update-tables', style={'display': 'none'}),
html.P(id='message')
],
style={
'margin-top': '50px'
}
) @app.callback(
Output('table-select', 'options'),
Input('refresh-tables', 'n_clicks')
)
def refresh_tables(n_clicks):
if n_clicks:
return [
{
'label': table,
'value': table
}
for table in pd.read_sql_query('SHOW TABLES', con=engine)['Tables_in_dash']
] return dash.no_update @app.callback(
[Output('dash-table', 'data'),
Output('dash-table', 'columns'),
Output('update-tables', 'style')],
Input('table-select', 'value')
)
def render_dash_table(value):
if value:
df = pd.read_sql_table(value, con=engine) return df.to_dict('records'), [
{'name': column, 'id': column}
for column in df.columns
], {'margin-top': '25px'} else:
return [], [], {'display': 'none'} @app.callback(
[Output('message', 'children'),
Output('message', 'style')],
Input('update-tables', 'n_clicks'),
[State('dash-table', 'data'),
State('table-select', 'value')]
)
def update_to_database(n_clicks, data, value): if n_clicks: try:
pd.DataFrame(data).to_sql(value, con=engine, if_exists='replace', index=False) return '更新成功!', {'color': 'green'}
except Exception as e:
return f'更新失败!{e}', {'color': 'red'} return dash.no_update if __name__ == '__main__':
app.run_server(debug=True)

  以上就是本文的全部内容,欢迎在评论区发表你的意见与观点。

(数据科学学习手札116)Python+Dash快速web应用开发——交互表格篇(中)的更多相关文章

  1. (数据科学学习手札115)Python+Dash快速web应用开发——交互表格篇(上)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  2. (数据科学学习手札117)Python+Dash快速web应用开发——交互表格篇(下)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  3. (数据科学学习手札102)Python+Dash快速web应用开发——基础概念篇

    本文示例代码与数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的新系列教程Python+Dash快 ...

  4. (数据科学学习手札108)Python+Dash快速web应用开发——静态部件篇(上)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  5. (数据科学学习手札109)Python+Dash快速web应用开发——静态部件篇(中)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  6. (数据科学学习手札118)Python+Dash快速web应用开发——特殊部件篇

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  7. (数据科学学习手札103)Python+Dash快速web应用开发——页面布局篇

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  8. (数据科学学习手札110)Python+Dash快速web应用开发——静态部件篇(下)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  9. (数据科学学习手札123)Python+Dash快速web应用开发——部署发布篇

    1 简介 这是我的系列教程Python+Dash快速web应用开发的第二十期,在上一期中我介绍了利用内网穿透的方式,将任何可以联网的电脑作为"服务器"向外临时发布你的Dash应用. ...

随机推荐

  1. Scalability & Scale-up & Scale-out

    Scalability & Scale-up & Scale-out 架构,弹性,伸缩性 Scalability 可扩展性 https://en.wikipedia.org/wiki/ ...

  2. vue & $router & History API

    vue & $router gotoTemplateManage(e) { e.preventDefault(); this.$router.push({ path: `/operate-to ...

  3. 类属性和__init__的实例属性有何区别?进来了解一下吧

    真的是随笔写的一篇,以防日后记忆模糊,特此记录.大佬勿喷 疑问:类属性和实例属性有何区别? 正题,代码如下 age为People类的属性(称为类属性) name是在__init__方法下,在创建实例对 ...

  4. 配置安装oh-my-bash

    背景 最近项目上有用到petalinux,所以只能在bash环境下使用命令行,所以不能使用oh-my-zsh 之前看一个dalao用oh-my-bash来规避这个问题.所以这里试一下安装oh-my-b ...

  5. 为什么我们在定义HashMap的时候,就指定它的初始化大小呢

    在当我们对HashMap初始化时没有设置初始化容量,系统会默认创建一个容量为16的大小的集合.当HashMap的容量值超过了临界值(默认16*0.75=12)时,HashMap将会重新扩容到下一个2的 ...

  6. Bitter.NotifyOpenPaltform : HTTP 异步消息接收调度中心—开源贡献 之 一:简介

    现在互联网的系统越来越趋向于复杂,从单体系统到现在的微服务体系演变.公司与公司的分工也越来越明确. 大数据公司提供了大数据服务 人脸识别公司提供了人脸识别服务 OCR 公司提供了专业的OCR 服务 车 ...

  7. Markdown基础使用方法

    Markdown基础使用方法 标题的几种用法 * 选中标题(Ctrl+1~Crtl+6),分别为标题1-6.* #+空格+内容 为一级标题##+空格+内容为二级标题:以此类推. 字体快捷键及使用方法 ...

  8. MySQL注入流程

    目录 确认注入点 信息收集 数据获取 提权 写个MySQL注入流程的大纲,类似一份全局地图,能指导下一步工作.MySQL注入流程分为四步: 确认注入点 信息收集 数据获取 提权 确认注入点 参考:ht ...

  9. 数据采集组件:Flume基础用法和Kafka集成

    本文源码:GitHub || GitEE 一.Flume简介 1.基础描述 Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统,Flume支持在日志系统中 ...

  10. Prometheus + Spring Boot 应用监控

    1.  Prometheus是什么 Prometheus是一个具有活跃生态系统的开源系统监控和告警工具包.一言以蔽之,它是一套开源监控解决方案. Prometheus主要特性: 多维数据模型,其中包含 ...