(数据科学学习手札109)Python+Dash快速web应用开发——静态部件篇(中)
本文示例代码已上传至我的
Github仓库https://github.com/CNFeffery/DataScienceStudyNotes
1 简介
这是我的系列教程Python+Dash快速web应用开发的第七期,在上一期的文章中,我们对Dash生态里常用的一些简单静态部件进行了介绍和功能展示,并且get到dcc.Markdown()这种非常方便的静态部件。
而在今天的教程内容中,我将带大家学习Dash中渲染网页静态表格的常用方法,并在最后的例子中教大家如何配合Dash,简简单单编写一个数据库查询应用~
图1
2 在Dash中渲染静态表格
在Dash中渲染静态表格,方法有很多,而我们今天要学习的方法,是配合之前文章介绍过的第三方拓展dash_bootstrap_components中的Table()部件,借助bootstrap的特性来快速创建美观的静态表格:
图2
## 2.1 静态表格的构成
要学习如何基于Dash在前端中渲染出一张静态表格,首先我们需要学习其元素构成,Dash延续html中table标签相关概念,由Table()、Thead()、Tbody()、Tr()、Th()以及Td()等6个部件来构成一张完整的表,先从一个简单的例子出发:
app1.py
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
app = dash.Dash(__name__)
app.layout = html.Div(
dbc.Container(
dbc.Table(
[
html.Thead(
html.Tr(
[
html.Th('第一列'),
html.Th('第二列'),
]
)
),
html.Tbody(
[
html.Tr(
[
html.Td('一行一列'),
html.Td('一行二列'),
]
),
html.Tr(
[
html.Td('二行一列'),
html.Td('二行二列'),
]
)
]
)
]
),
style={
'margin-top': '50px' # 设置顶部留白区域高度
}
)
)
if __name__ == '__main__':
app.run_server(debug=True)
图3
注意,我们这里使用到的Table()部件来自dash_bootstrap_components,而表格其余的构成部件均来自Dash原生的dash_html_components库,这些部件分别的作用如下:
- Table()
Table()是一张静态表格最外层的部件,而之所以选择dash_bootstrap_components中的Table(),是因为其自带了诸多实用参数,常用的如下:
bordered:bool型,用于设置是否保留表格外边框线
borderless:bool型,用于设置是否删除表格内部单元格框线
striped:bool型,用于设置是否对数值行应用斑马着色方案,即相邻行背景色不同
dark:bool型,用于设置是否应用暗黑主题
hover:bool型,当设置为True时,鼠标悬浮于某行会有对应的效果
通过上述参数,我们就可以改变静态表格的整体效果,譬如设置dark=True之后的app1.py效果如下:
图4
- Thead()与Tbody()
在部件Table()之下一级需要子元素Thead()与Tbody(),分别用于存放表头信息以及表数值内容信息。
- Tr()、Th()与Td()
经过前面Table()嵌套Thead()与Tbody()的过程之后,我们就可以分别开始在表头区域和数值区域正式组织数据内容。
既然是一张表格,那么还是要按照先行后列的网格方式组织内容。而Tr()部件的作用就是作为行容器,其内部嵌套的子元素则是表格中每个单元格位置上的元素。
其中在Thead()嵌套的Tr()内部,需要使用Th()来设置每列的字段名称,而在Tbody()嵌套的Tr()内部,Td()与Th()都可以用来设置每个单元格的数值内容,只不过Th()在表现单元格数值时有加粗效果:
app2.py
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
app = dash.Dash(__name__)
app.layout = html.Div(
dbc.Container(
dbc.Table(
[
html.Thead(
html.Tr(
[
html.Th('字段1'),
html.Th('字段2')
]
)
),
html.Tbody(
[
html.Tr(
[
html.Th('1'),
html.Td('test')
]
),
html.Tr(
[
html.Th('2'),
html.Td('test')
]
),
html.Tr(
[
html.Td('3'),
html.Td('test')
]
)
]
)
],
striped=True
),
style={
'margin-top': '50px' # 设置顶部留白区域高度
}
)
)
if __name__ == '__main__':
app.run_server(debug=True)
图5
而Th()与Td()均有额外参数colSpan与rowSpan,可以传入整数,来实现横向或纵向合并单元格的效果,譬如下面的例子:
app3.py
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
app = dash.Dash(__name__)
app.layout = html.Div(
dbc.Container(
dbc.Table(
[
html.Thead(
html.Tr(
[
html.Th('字段1'),
html.Th('字段2'),
html.Th('字段3'),
html.Th('字段4'),
]
)
),
html.Tbody(
[
html.Tr(
[
html.Th('1'),
# style设置水平居中
html.Td('colSpan=2', colSpan=2, style={'text-align': 'center'}),
html.Td('test'),
]
),
html.Tr(
[
html.Th('2'),
html.Td('test'),
# style设置垂直居中
html.Td('rowSpan=2', rowSpan=2, style={'vertical-align': 'middle'}),
html.Td('test')
]
),
html.Tr(
[
html.Th('3'),
html.Td('test'),
html.Td('test')
]
)
]
)
],
striped=True,
bordered=True
),
style={
'margin-top': '50px' # 设置顶部留白区域高度
}
)
)
if __name__ == '__main__':
app.run_server(debug=True)
图6
2.2 快速表格渲染
2.2.1 利用列表推导快速渲染静态表格
通过前面的内容,我们知晓了在Dash中如果渲染一张带有样式的静态表格,而日常需求中,面对批量的数据,我们当然不可能手动编写整张表对应的代码,对于数量较多的表格,我们可以配合Python中常用的列表推导来实现。
比如下面的例子:
app4.py
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
import pandas as pd
import numpy as np
fake_df = pd.DataFrame(np.random.rand(1000).reshape(200, 5))
fake_df.rename(lambda s: f'字段{s}', axis=1, inplace=True) # 批量格式化列名
app = dash.Dash(__name__)
app.layout = html.Div(
dbc.Container(
dbc.Table(
[
html.Thead(
html.Tr(
[html.Th('行下标', style={'text-align': 'center'})] +
[
html.Th(column, style={'text-align': 'center'})
for column in fake_df.columns
]
)
),
html.Tbody(
[
html.Tr(
[html.Th(f'#{idx}', style={'text-align': 'center'})] +
[
html.Td(row[column], style={'text-align': 'center'})
for column in fake_df.columns
]
)
for idx, row in fake_df.iterrows()
]
)
],
striped=True,
bordered=True
),
style={
'margin-top': '50px' # 设置顶部留白区域高度
}
)
)
if __name__ == '__main__':
app.run_server(debug=True)
在生成表头和每行内容时应用列表推导,使得我们的代码更加简洁。
图7
2.2.2 利用from_dataframe()快速渲染表格
上述的列表推导方式虽说已经简洁了很多,但dash_bootstrap_components还提供了Table.from_dataframe()方法,可以直接传入pandas数据框来快速制作简易的静态表格。
它的样式相关参数与dbc.Table()一致,缺点是自定义表格内部元素样式的自由度没有前面列表推导高:
app5.py
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
import pandas as pd
import numpy as np
fake_df = pd.DataFrame(np.random.rand(1000).reshape(200, 5))
fake_df.rename(lambda s: f'字段{s}', axis=1, inplace=True) # 批量格式化列名
app = dash.Dash(__name__)
app.layout = html.Div(
dbc.Container(
# 一行代码渲染静态表格
dbc.Table.from_dataframe(fake_df, striped=True),
style={
'margin-top': '50px' # 设置顶部留白区域高度
}
)
)
if __name__ == '__main__':
app.run_server(debug=True)
图8
3 自制简易的数据库查询系统
在学习了今天的内容之后,我们就可以创建很多以表格为主体内容的web应用,典型如数据库查询系统,我们以Postgresql为例,配合pandas与sqlalchemy的相关功能,来快速打造一个简单的数据库查询系统。
首先将本期附件中的所有数据表利用下面的代码导入目标数据库中:
图9
图10
接着只需要配合Dash,短短的几十行代码就可以实现下面的效果:
图11
对应代码如下:
app6.py
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
import pandas as pd
from sqlalchemy import create_engine
postgres_url = 'postgresql://postgres:填入你的密码@localhost:5432/Dash'
engine = create_engine(postgres_url)
app = dash.Dash(__name__)
app.layout = html.Div(
dbc.Container(
[
dbc.Row(
[
dbc.Col(dbc.Button('更新数据库信息', id='refresh-db', style={'width': '100%'}), width=2),
dbc.Col(dcc.Dropdown(id='db-table-names', placeholder='选择库中数据表', style={'width': '100%'}), width=4),
dbc.Col(dbc.Button('查询', id='query', style={'width': '100%'}), width=1)
]
),
html.Hr(),
dbc.Row(
[
dbc.Col(
id='query-result'
)
]
)
],
style={
'margin-top': '50px' # 设置顶部留白区域高度
}
)
)
@app.callback(
Output('db-table-names', 'options'),
Input('refresh-db', 'n_clicks'),
prevent_initial_call=True
)
def query_data_records(n_clicks):
# 提取目标表格并查询其最多前500行记录
table_names = pd.read_sql_query("select tablename from pg_tables where schemaname='public'", con=engine)
return [{'label': name, 'value': name} for name in table_names['tablename']]
@app.callback(
Output('query-result', 'children'),
Input('query', 'n_clicks'),
State('db-table-names', 'value'),
prevent_initial_call=True
)
def refresh_table_names(n_clicks, value):
if value:
query_result = pd.read_sql_query(f'select * from {value} limit 500', con=engine)
return html.Div(dbc.Table.from_dataframe(query_result, striped=True), style={'height': '600px', 'overflow': 'auto'})
else:
return dash.no_update
if __name__ == '__main__':
app.run_server(debug=True)
以上就是本文的全部内容,欢迎在评论区与我进行讨论~
(数据科学学习手札109)Python+Dash快速web应用开发——静态部件篇(中)的更多相关文章
- (数据科学学习手札108)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 ...
- (数据科学学习手札118)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快 ...
- (数据科学学习手札115)Python+Dash快速web应用开发——交互表格篇(上)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札116)Python+Dash快速web应用开发——交互表格篇(中)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札117)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 ...
- (数据科学学习手札105)Python+Dash快速web应用开发——回调交互篇(中)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
随机推荐
- 树的直径&树的重心
树的直径 定义 那么树上最远的两个点,他们之间的距离,就被称之为树的直径. 树的直径的性质 1. 直径两端点一定是两个叶子节点. 2. 距离任意点最远的点一定是直径的一个端点,这个基于贪心求直径方法的 ...
- CTGU_训练实录
前言 之前做题都没有感觉,慢慢出去比赛后,打Codeforces,看别的人博客,知乎上的讨论,慢慢的对算法有一些自己的思考.特写是最近看知乎上别人说的Dijkstra利用水流去理解,LCA的学习,感觉 ...
- 2019牛客暑期多校训练营(第一场)H XOR(线性基)
题意:给你n个数字,然后让你求所有满足异或和为0的子集的大小之和. 先对n个数求线性基,设线性基大小为r,可以分别计算线性基内数的贡献和线性基外数的贡献 1.线性基外:共n-r个数,枚举每个数x,将线 ...
- Codeforces Round #657 (Div. 2) B. Dubious Cyrpto(数论)
题目链接:https://codeforces.com/contest/1379/problem/B 题意 给出三个正整数 $l,r,m$,判断在区间 $[l,r]$ 内是否有 $a,b,c$ 满足存 ...
- Codeforces Round #628 (Div. 2) D. Ehab the Xorcist(异或,思维题)
题意: 寻找异或后值为 u,相加后和为 v 的最短数组. 思路: 异或得 u ,则 v 至少应大于等于 u ,且多出来的部分可以等分为两份相消. 即初始数组为 u , (v-u)/2 , (v-u)/ ...
- Educational Codeforces Round 89 (Rated for Div. 2) A. Shovels and Swords(贪心/数学)
题目链接:https://codeforces.com/contest/1366/problem/A 题意 有两个数 $a$ 和 $b$,每次可以选择从一个数中取 $2$,另一个数中取 $1$,问最多 ...
- 南阳ccpc C题 The Battle of Chibi 树状数组+dp
题目: Cao Cao made up a big army and was going to invade the whole South China. Yu Zhou was worried ab ...
- hdu 6863 Isomorphic Strings 哈希+求公因子
题意: t组输入,每组数据输入一个整数n,代表字符串长度.下面再输入一个字符串 你需要判断这个字符串能不能分成大于1段,且这些段的最小表示法是一样的 例如:abccab,它可以分成2段,分别是abc和 ...
- python爬虫下载小视频和小说(基础)
下载视频: 1 from bs4 import BeautifulSoup 2 import requests 3 import re 4 import urllib 5 6 7 def callba ...
- 【ybt金牌导航1-2-3】折线统计
折线统计 题目链接:ybt金牌导航1-2-3 题目大意 在一个图上有一些点,保证任意两个点的横纵坐标都不相同. 要你选一些集合,按 x 坐标排序依次连接,会构成一些连续上升下降的折线,问你折线数量是 ...