您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么用Python快速開發(fā)在線數(shù)據(jù)庫更新修改工具”,在日常操作中,相信很多人在怎么用Python快速開發(fā)在線數(shù)據(jù)庫更新修改工具問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么用Python快速開發(fā)在線數(shù)據(jù)庫更新修改工具”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
這是我的系列教程「Python+Dash快速web應(yīng)用開發(fā)」的第十三期,在上一期中,我們一起認(rèn)識了Dash自帶的交互式表格組件dash_table,并學(xué)會了如何自定義表格中不同部分的樣式。
而今天的教程,我們將繼續(xù)深入認(rèn)識dash_table的更多交互方面的功能,學(xué)習(xí)如何為渲染出的表格分頁,并添加動態(tài)內(nèi)容修改等交互功能。
圖1
dash_table的核心功能是賦予用戶與圖表進(jìn)行快捷交互的能力,下面我們來學(xué)習(xí)其基礎(chǔ)常用的一些交互功能:
當(dāng)我們要展示的數(shù)據(jù)行數(shù)較多時,在網(wǎng)頁中渲染可以選擇分頁,這在dash_table中實(shí)現(xiàn)起來比較方便,根據(jù)數(shù)據(jù)傳遞方式的不同,可以分為「前端分頁」與「后端分頁」:
前端分頁顧名思義,就是在我們訪問Dash應(yīng)用時,表格內(nèi)所有頁面的數(shù)據(jù)一次性加載完成,適合數(shù)據(jù)量不大的情況,將數(shù)據(jù)存儲壓力轉(zhuǎn)移到瀏覽器端。
通過參數(shù)page_size設(shè)置每頁要顯示的記錄行數(shù),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, # 設(shè)置單頁顯示15行記錄行數(shù) 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 后端分頁
雖然前端分頁簡單易用,但當(dāng)我們的數(shù)據(jù)很大時,強(qiáng)行使用前端分頁會給「網(wǎng)絡(luò)傳輸」和「瀏覽器端」帶來不小的延遲和內(nèi)存壓力,嚴(yán)重影響用戶體驗(yàn),因此Dash貼心地為我們準(zhǔn)備了「后端分頁」方式。
這時首先我們得為DataTable設(shè)置參數(shù)page_action='custom',這是使用后端分頁的先決條件,接下來我們需要認(rèn)識一些新的參數(shù):
page_current,int型,對應(yīng)當(dāng)前翻到的頁碼;
page_count,int型,對應(yīng)顯示的總頁數(shù);
我們在使用「后端分頁」時,實(shí)際上就是通過用戶當(dāng)前翻到的頁碼,以及設(shè)定的page_size,來動態(tài)地在翻頁后加載對應(yīng)批次的數(shù)據(jù),并控制顯示的總頁數(shù),參考下面這個簡單的例子:
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, # 設(shè)置單頁顯示15行記錄行數(shù) 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)
可以看到,即使我們完整的數(shù)據(jù)集被我concat到24萬行,加載應(yīng)用以及網(wǎng)頁內(nèi)翻頁時依然輕松自如毫無壓力,在實(shí)際應(yīng)用中你還可以將翻頁部分改成受到LIMIT與OFFSET控制的數(shù)據(jù)庫查詢過程,使得應(yīng)用運(yùn)行的更加快速高效:
圖3
講完了分頁翻頁,接下來我們來學(xué)習(xí)dash_table中更加強(qiáng)大的功能——單元格內(nèi)容編輯。
一個現(xiàn)代化的web應(yīng)用當(dāng)然不能局限于僅僅查看數(shù)據(jù)這么簡單,Dash同樣賦予了我們雙擊數(shù)據(jù)表單元格進(jìn)行數(shù)據(jù)編輯的能力,首先得設(shè)置參數(shù)editable=True,即開啟表格編輯模式,接下來就可以對數(shù)據(jù)區(qū)域單元格進(jìn)行任意的雙擊選中編輯。
不過Dash默認(rèn)的單元格被選中的樣式忒丑了(是粉色的你敢信),因此我們可以利用下面的參數(shù)設(shè)置方式來自定義美化:
style_data_conditional=[ { # 對選中狀態(tài)下的單元格進(jìn)行自定義樣式 "if": {"state": "selected"}, "background-color": "#b3e5fc", "border": "none" }, ]
來看一個形象的例子,我們對「前端分頁」方式渲染出的表格進(jìn)行隨意的修改,并在下方對利用pandas的compare比較出的數(shù)據(jù)框之間的差異結(jié)果進(jìn)行打?。?/p>
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=[ { # 對選中狀態(tài)下的單元格進(jìn)行自定義樣式 "if": {"state": "selected"}, "background-color": "#b3e5fc", "border": "none" }, ] ), html.H4('與原表格內(nèi)容比較:', 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)
可以看到,我們成功地對指定單元格元素進(jìn)行了修改。
圖4
在學(xué)習(xí)完今天的內(nèi)容之后,我們就可以開發(fā)一個簡單的,可在線自由修改并同步變動到數(shù)據(jù)庫的小工具,這里我們以MySQL數(shù)據(jù)庫為例,對示例表進(jìn)行修改和更新:
首先我們利用下列代碼向示例數(shù)據(jù)庫中新建表格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
接下來我們就以創(chuàng)建好的tips表為例,開發(fā)一個Dash應(yīng)用,進(jìn)行數(shù)據(jù)的修改和更新到數(shù)據(jù)庫:
圖6
效果非常的不錯,你可以在我這個簡單示例的基礎(chǔ)上,拓展更多新功能,也可以采取后端分頁+條件修改的方式來應(yīng)對大型數(shù)據(jù)表的修改,全部代碼如下:
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('更新數(shù)據(jù)表', 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=[ { # 對選中狀態(tài)下的單元格進(jìn)行自定義樣式 "if": {"state": "selected"}, "background-color": "#b3e5fc", "border": "none" }, ] ), dbc.Button('同步變動到數(shù)據(jù)庫', 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)
到此,關(guān)于“怎么用Python快速開發(fā)在線數(shù)據(jù)庫更新修改工具”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。