<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          秀啊,用Python快速開發(fā)在線數(shù)據(jù)庫更新修改工具

          共 20652字,需瀏覽 42分鐘

           ·

          2021-04-19 14:36


          ?

          本文示例代碼已上傳至我的Github倉庫https://github.com/CNFeffery/DataScienceStudyNotes

          ?

          1 簡(jiǎn)介

          這是我的系列教程「Python+Dash快速web應(yīng)用開發(fā)」的第十三期,在上一期中,我們一起認(rèn)識(shí)了Dash自帶的交互式表格組件dash_table,并學(xué)會(huì)了如何自定義表格中不同部分的樣式。

          而今天的教程,我們將繼續(xù)深入認(rèn)識(shí)dash_table的更多交互方面的功能,學(xué)習(xí)如何為渲染出的表格分頁,并添加動(dòng)態(tài)內(nèi)容修改等交互功能。

          圖1

          2 dash_table的基礎(chǔ)交互能力

          dash_table的核心功能是賦予用戶與圖表進(jìn)行快捷交互的能力,下面我們來學(xué)習(xí)其基礎(chǔ)常用的一些交互功能:

          2.1 分頁翻頁

          當(dāng)我們要展示的數(shù)據(jù)行數(shù)較多時(shí),在網(wǎng)頁中渲染可以選擇分頁,這在dash_table中實(shí)現(xiàn)起來比較方便,根據(jù)數(shù)據(jù)傳遞方式的不同,可以分為「前端分頁」「后端分頁」

          2.1.1 前端分頁

          前端分頁顧名思義,就是在我們?cè)L問Dash應(yīng)用時(shí),表格內(nèi)所有頁面的數(shù)據(jù)一次性加載完成,適合數(shù)據(jù)量不大的情況,將數(shù)據(jù)存儲(chǔ)壓力轉(zhuǎn)移到瀏覽器端。

          通過參數(shù)page_size設(shè)置每頁要顯示的記錄行數(shù),Dash會(huì)自動(dòng)幫我們分好頁,并配上翻頁部件:

          ?

          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 后端分頁

          雖然前端分頁簡(jiǎn)單易用,但當(dāng)我們的數(shù)據(jù)很大時(shí),強(qiáng)行使用前端分頁會(huì)給「網(wǎng)絡(luò)傳輸」「瀏覽器端」帶來不小的延遲和內(nèi)存壓力,嚴(yán)重影響用戶體驗(yàn),因此Dash貼心地為我們準(zhǔn)備了「后端分頁」方式。

          這時(shí)首先我們得為DataTable設(shè)置參數(shù)page_action='custom',這是使用后端分頁的先決條件,接下來我們需要認(rèn)識(shí)一些新的參數(shù):

          page_current,int型,對(duì)應(yīng)當(dāng)前翻到的頁碼;

          page_count,int型,對(duì)應(yīng)顯示的總頁數(shù);

          我們?cè)谑褂?strong>「后端分頁」時(shí),實(shí)際上就是通過用戶當(dāng)前翻到的頁碼,以及設(shè)定的page_size,來動(dòng)態(tài)地在翻頁后加載對(duì)應(yīng)批次的數(shù)據(jù),并控制顯示的總頁數(shù),參考下面這個(gè)簡(jiǎn)單的例子:

          ?

          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

          # 壓力測(cè)試
          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í)依然輕松自如毫無壓力,在實(shí)際應(yīng)用中你還可以將翻頁部分改成受到LIMITOFFSET控制的數(shù)據(jù)庫查詢過程,使得應(yīng)用運(yùn)行的更加快速高效:

          圖3

          2.2 對(duì)單元格內(nèi)容進(jìn)行編輯

          講完了分頁翻頁,接下來我們來學(xué)習(xí)dash_table中更加強(qiáng)大的功能——單元格內(nèi)容編輯。

          一個(gè)現(xiàn)代化的web應(yīng)用當(dāng)然不能局限于僅僅查看數(shù)據(jù)這么簡(jiǎn)單,Dash同樣賦予了我們雙擊數(shù)據(jù)表單元格進(jìn)行數(shù)據(jù)編輯的能力,首先得設(shè)置參數(shù)editable=True,即開啟表格編輯模式,接下來就可以對(duì)數(shù)據(jù)區(qū)域單元格進(jìn)行任意的雙擊選中編輯。

          不過Dash默認(rèn)的單元格被選中的樣式忒丑了(是粉色的你敢信),因此我們可以利用下面的參數(shù)設(shè)置方式來自定義美化:

          style_data_conditional=[
                          {
                              # 對(duì)選中狀態(tài)下的單元格進(jìn)行自定義樣式
                              "if": {"state""selected"},
                              "background-color""#b3e5fc",
                              "border""none"
                          },
                      ]

          來看一個(gè)形象的例子,我們對(duì)「前端分頁」方式渲染出的表格進(jìn)行隨意的修改,并在下方對(duì)利用pandascompare比較出的數(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=[
                          {
                              # 對(duì)選中狀態(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)

          可以看到,我們成功地對(duì)指定單元格元素進(jìn)行了修改。

          圖4

          3 開發(fā)數(shù)據(jù)庫內(nèi)容在線更新工具

          在學(xué)習(xí)完今天的內(nèi)容之后,我們就可以開發(fā)一個(gè)簡(jiǎn)單的,可在線自由修改并同步變動(dòng)到數(shù)據(jù)庫的小工具,這里我們以MySQL數(shù)據(jù)庫為例,對(duì)示例表進(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ā)一個(gè)Dash應(yīng)用,進(jìn)行數(shù)據(jù)的修改和更新到數(shù)據(jù)庫:

          圖6

          效果非常的不錯(cuò),你可以在我這個(gè)簡(jiǎn)單示例的基礎(chǔ)上,拓展更多新功能,也可以采取后端分頁+條件修改的方式來應(yīng)對(duì)大型數(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=[
                          {
                              # 對(duì)選中狀態(tài)下的單元格進(jìn)行自定義樣式
                              "if": {"state""selected"},
                              "background-color""#b3e5fc",
                              "border""none"
                          },
                      ]
                  ),
                  dbc.Button('同步變動(dòng)到數(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)

          以上就是本文的全部?jī)?nèi)容,歡迎在評(píng)論區(qū)發(fā)表你的意見與觀點(diǎn)。

          推薦閱讀
          誤執(zhí)行了rm -fr /*之后,除了跑路還能怎么辦?!
          程序員必備58個(gè)網(wǎng)站匯總
          大幅提高生產(chǎn)力:你需要了解的十大Jupyter Lab插件

          瀏覽 42
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  在线视频免费电影亚洲色图 | 中文字字幕一区二区三区四区五区 | 99精品视频在线免费观看 | 一区二区区区区区一个三区在线观看地址 | se色综合 |