用Python轻松开发数据库取数下载工具
本文示例代碼已上傳至我的Github倉庫https://github.com/CNFeffery/DataScienceStudyNotes
?1 簡介
這是我的系列教程「Python+Dash快速web應用開發」的第十四期,在前兩期中,我們針對dash_table的自定義樣式、前后端分頁、單元格內容編輯等特點展開了介紹。
而在dash_table中還有很多高級特性,可以極大程度上豐富DataTable()所渲染網頁表格的交互能力,今天的文章作為「交互表格篇」的下篇,我們就來一起學習其中比較實用的一些特性。
圖12 dash_table的更多實用功能
2.1 更多表格交互特性
上一期文章最后我們學習了通過設置參數editable=True,使得渲染出的表格可以通過鼠標雙擊進行編輯,而dash_table除此之外,還有更多實用的交互能力:
2.1.1 按列排序
「普通單列排序」
在DataTable()中,我們只需要設置參數sort_action='native',即可開啟列排序功能,此時每一列列名單元格內都會出現部件供我們點擊切換排序方式:
?app1.py
?import?dash import?dash_table import?dash_bootstrap_components?as?dbcimport?seaborn?as?snsdf?=?sns.load_dataset('iris')app?=?dash.Dash(__name__)app.layout?=?dbc.Container([dash_table.DataTable(data=df.to_dict('records'),columns=[{'name':?column,?'id':?column}for?column?in?df.columns],style_table={'height':?'500px','overflow-y':?'auto'},sort_action='native')],style={'margin-top':?'50px'} )if?__name__?==?'__main__':app.run_server(debug=True) 圖2「基于后端排序的多列排序」
在DataTable()中設置sort_action='native'時,對應的是「按列排序」的前端模式,也即是數據一次性灌注到瀏覽器的前提下進行排序,這種方式不僅不適合大型數據集,而且只支持「單列排序」。
而當數據渲染方式為后端模式時,我們通過設置參數sort_action='custom'以及sort_mode='multi',配合在回調中獲取屬性sort_by中記錄的參與排序的列名及升序降序方式,就可以實現多列排序。
我們在上一期的app2.py的基礎上修改得到下面的例子:
?app2.py
?import?dash import?dash_bootstrap_components?as?dbc import?dash_table from?dash.dependencies?import?Input,?Outputimport?seaborn?as?snsdf?=?sns.load_dataset('iris') 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'},sort_action='custom',sort_mode='multi'))],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'),Input('dash-table',?'sort_by')] ) def?refresh_page_data(page_current,?page_size,?sort_by):if?sort_by:return?(df.sort_values([col['column_id']?for?col?in?sort_by],ascending=[col['direction']?==?'asc'for?col?in?sort_by]).iloc[page_current?*?page_size:(page_current?+?1)?*?page_size].to_dict('records'),1?+?df.shape[0]?//?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) 圖32.1.2 按列條件篩選
除了基于指定字段進行排序之外,dash_table還支持列的條件篩選,設置filter_action="native",就可以開啟基礎的按列條件篩選功能,此時每一列表頭下都會多出供用戶輸入篩選條件的單元格:
?app3.py
?import?dash import?dash_table import?dash_bootstrap_components?as?dbcimport?seaborn?as?snsdf?=?sns.load_dataset('iris')app?=?dash.Dash(__name__)app.layout?=?dbc.Container([dash_table.DataTable(data=df.to_dict('records'),columns=[{'name':?column,?'id':?column}for?column?in?df.columns],#?自定義條件篩選單元格樣式style_filter={'font-family':?'Times?New?Romer','background-color':?'#e3f2fd'},style_table={'height':?'500px','overflow-y':?'auto'},style_header={'font-family':?'Times?New?Romer','font-weight':?'bold','text-align':?'center'},style_data={'font-family':?'Times?New?Romer','text-align':?'center'},filter_action="native")],style={'margin-top':?'50px'} )if?__name__?==?'__main__':app.run_server(debug=True) 圖4而dash_table中自帶的條件篩選語法很豐富,有條件的朋友可以前往https://dash.plotly.com/datatable/filtering了解更多。
而dash_table同樣可以實現后端篩選,和前面的后端排序類似,主要利用filter_query屬性的回調變化在后臺基于pandas等框架進行數據篩選,比較簡單,這里就不再贅述。
2.2 自帶的數據表格下載功能
dash_table還自帶了將當前所渲染的表格內容直接下載為csv或xlsx格式文件的簡易功能,通過參數export_format設置導出的文件格式,但自帶的下載按鈕樣式比較丑,如果你對此有比較高的要求,還是建議結合之前的「上傳下載篇」自己設計相關功能:
圖52.3 凍結首行
通過設置參數fixed_rows={'headers': True},我們可以實現下滑查看表格的過程中,始終保持表頭被凍結:
圖63 開發一個在線取數工具
在學習完今天的內容之后,我們來結合之前「上傳下載篇」中提到的下載功能,來制作一個簡單的對指定數據庫中的數據表進行快速條件篩選并下載的工具,其中DataTable的derived_virtual_data屬性記錄了經過排序、條件篩選等操作后當前顯示的表格數據:
圖7?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,?Outputfrom?flask?import?send_from_directoryimport?os import?uuid from?sqlalchemy?import?create_engine import?pandas?as?pdtry:os.mkdir("downloads") except?FileExistsError:passengine?=?create_engine('mysql+pymysql://root:mysql@localhost/DASH')app?=?dash.Dash(__name__)@app.server.route('/download/<file>') def?download(file):return?send_from_directory('downloads',?file)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"},],filter_action="native"),html.Br(),html.A(id='download-url',?target="_blank")],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')],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]else:return?[],?[]@app.callback([Output("download-url",?"href"),Output("download-url",?"children")],[Input("dash-table",?"derived_virtual_data"),Input("dash-table",?"filter_query")],prevent_initial_call=True ) def?download_table(derived_virtual_data,?filter_query):if?derived_virtual_data:print(derived_virtual_data)filename?=?f"output_{uuid.uuid1()}.xlsx"pd.DataFrame(derived_virtual_data).to_excel("downloads/"?+?filename,?index=False)return?"/download/"?+?filename,?"下載當前狀態表格"return?"",?""if?__name__?==?'__main__':app.run_server(debug=True)以上就是本文的全部內容,歡迎在評論區發表你的意見與觀點。
推薦閱讀
Pandas處理數據太慢,來試試Polars吧!
懶人必備!只需一行代碼,就能導入所有的Python庫
絕!關于pip的15個使用小技巧
介紹10個常用的Python內置函數,99.99%的人都在用!
可能是全網最完整的 Python 操作 Excel庫總結!
總結
以上是生活随笔為你收集整理的用Python轻松开发数据库取数下载工具的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实用脚本!利用 Python 对 PDF
- 下一篇: 告别加班:一个让你不再重复工作的技能