当前位置:首页 > IT科技类资讯

秀啊,用Python快速开发在线数据库更新修改工具

 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万行,加载应用以及网页内翻页时依然轻松自如毫无压力,在实际应用中你还可以将翻页部分改成受到LIMIT与OFFSET控制的数据库查询过程,使得应用运行的更加快速高效:

图3

2.2 对单元格内容进行编辑

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

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

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

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

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

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) 

分享到:

滇ICP备2023006006号-16