当前位置: 首页 > 科技观察

使用Python轻松开发一个数据库访问下载工具

时间:2023-03-15 23:02:20 科技观察

1简介这是我的《Python+Dash快速Web应用开发》系列教程的第十四期。引入了分页和单元格内容编辑等功能。并且dash_table中还有很多高级特性,可以大大丰富DataTable()渲染的web表格的交互能力。今天的文章是“交互式表格”的下一篇,让我们来学习一些比较实用的特性。图12dash_table更多实用功能2.1表格更多交互功能上一篇我们了解到,通过设置参数editable=True,可以双击鼠标编辑渲染的表格,dash_table还有其他功能更实用交互能力:2.1.1按列排序普通的单列排序在DataTable()中,我们只需要设置参数sort_action='native'即可启用列排序功能。这时候单元格中会显示每列的列名出现一个组件供我们点击切换排序方式:.layout=dbc.Container([dash_table.DataTable(data=df.to_dict('records'),columns=[{'name':column,'id':column}forcolumnindf.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.pyimportdashimportdash_bootstrap_componentsasdbcimportdash_tablefromdash.dependenciesimportInput,Outputimportseabornassnsdf=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}forcolumnindf.columns],page_size=15,#设置单页显示15行记录page_action='custom',page_current=0,style_header={'font-family':'TimesNewRomer','font-weight':'bold','text-align':'center'},style_data={'font-family':'TimesNewRomer','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')])defrefresh_page_data(page_current,page_size,sort_by):ifsort_by:return(df.sort_values([col['column_id']forcolinsort_by],ascending=[col['direction']=='asc'forcolinsort_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"以启用按列条件的基本过滤器。这时候,每个列头都会有更多的单元格供用户输入过滤条件:DataTable(data=df.to_dict('records'),columns=[{'name':column,'id':column}forcolumnindf.columns],#customconditionfiltercellstyle_filter={'font-family':'TimesNewRomer','background-color':'#e3f2fd'},style_table={'height':'500px','overflow-y':'auto'},style_header={'font-family':'TimesNewRomer','font-weight':'bold','text-align':'center'},style_data={'font-family':'TimesNewRomer','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.2Thebuilt-indatatabledownloadfunctiondash_tablealsocomeswithasimplefunctionofdirectlydownloadingthecurrentlyrenderedtablecontentasacsvorxlsxformatfile.Theexportedfileformatissetthroughtheparameterexport_format,butthebuilt-indownloadbuttonstyleisugly,ifyouhaverelativelyhighrequirementsforthis,itisrecommendedtodesignrelatedfunctionsincombinationwiththeprevious"UploadandDownload":Figure52.3FreezingthefirstrowBysettingtheparameterfixed_rows={'headers':True},wecanrealizetheslidingviewtableDuringtheprocess,thetableheaderisalwayskeptfrozen:Figure63DevelopinganonlineaccesstoolAfterlearningtoday'scontent,let'scombinethedownloadfunctionmentionedintheprevious"UploadandDownload"tocreateasimplepairspecified数据库中的数据表进行快速条件筛选并下载的工具,其中DataTable的derived_virtual_data属性记录了经过排序、条件筛选等操作后当前显示的表格数据:图7app4.pyimportdashimportdash_bootstrap_componentsasdbcimportdash_core_componentsasdccimportdash_html_componentsashtmlimportdash_tablefromdash.dependenciesimportInput,Outputfromflaskimportsend_from_directoryimportosimportuuidfromsqlalchemyimportcreate_engineimportpandasaspdtry:os.mkdir("downloads")exceptFileExistsError:passengine=create_engine('mysql+pymysql://root:mysql@localhost/DASH')app=dash.Dash(__name__)@app.server.route('/download/')defdownload(file):returnsend_from_directory('downloads',file)app.layout=dbc.Container([dbc.Row([dbc.Col(dbc.Button('updatedatatable',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':'TimesNewRomer','font-weight':'bold','text-align':'center'},style_data={'font-family':'TimesNewRomer','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'))derefresh_tables(n_clicks):ifn_clicks:return[{'label':table,'value':table}fortableinpd.read_sql_query('SHOWTABLES',con=engine)['Tables_in_dash']]returndash.no_update@app.callback([Output('dash-table','data'),Output('dash-table','columns')],Input('table-select','value'))defrender_dash_table(value):ifvalue:df=pd.read_sql_table(value,con=engine)returndf.to_dict('records'),[{'name':column,'id':column}forcolumnindf.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)defdownload_table(derived_virtual_data,filter_query):ifderived_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)