这是我的系列教程Python+Dash快速web应用开发的第十八期,通过前面十七期的内容,如果你有用心学习的话,那么恭喜你已经具备使用Dash编写常规web应用的能力了。
而在今天的教程中,我就将为大家介绍我在日常使用过程中总结出的一套针对Dash项目的前后端分离的项目结构基础范式,并以搭建全国七普部分数据可视化看板为例,供大家参考借鉴,从而更有条理的编写和管理Dash应用项目。
开门见山,我们直接先来一览今天要介绍的Dash基础项目结构:
+dash_demo_project/+assets/+css/+img/+js/favicon.ico+callbacks/+models/+views/app.pyserver.py在不考虑外部参数导入、用户登陆验证、应用部署等额外配置文件及功能内容的前提下,上面的结构就可以满足常规Dash应用的需求了。
在页面布局篇中我们提到过assets目录,它是官方推荐的用于存放我们的Dash应用所依赖静态资源文件的目录,如依赖的css、js、favicon.ico、各种图片及字体等静态资源,在本文的可视化看板案例中,assets目录资源放置情况如下:
+assets/+css/bootstrap.min.csscustom.css+img/wxgzh.pngzsxq.png+js/favicon.ico其中img目录下存放的是首页的两张二维码图片,在Dash中可以配合Img()与get_asset_url()来获取assets目录下指定文件路径并渲染:
html.Img(src=app.get_asset_url('img/zsxq.png'),style={'width':'100%'})而css目录下则放置了dash_bootstrap-components所依赖的css文件,而custom.css则是我自己编写的一些用于样式美化的css代码:
.nav-link.active{background-color:#4fc3f7!important;}#index-desc>*{font-size:26px;}.tabletd,.tableth{text-align:center;}直接放置于assets根目录下的favicon.ico则用来替换Dash默认的网页图标:
你可以根据自己Dash项目的实际需求灵活变通,譬如需要用到echarts就可以在js目录下放置echarts.min.js文件。
跟以往的例子不同,在严谨的Dash工程下,推荐构建单独的server.py文件来完成对Dash对象的实例化配置等工作,在今天的可视化看板案例中server.py比较简单,内容如下:
importdashapp=dash.Dash(__name__,suppress_callback_exceptions=True)#设置网页titleapp.title='七普部分数据看板'server=app.server2.2.3在app.py中编写前端骨架与路由如果你的Dash项目非常简单,那么fromserverimportapp之后,就可以像往常一样在app.py中组织你的前端与回调部分内容。
但如果你的Dash项目功能较为复杂,亦或是url联结的页面较多时,就可以只在app.py中编写前端layout骨架,包含了必要的Location()部件、保持不变的前端部分以及由url变化所触发的页面内容容器,譬如今天的可视化看板中左侧边栏部分以及Location()监听部件:
#路由总控@app.callback(Output('page-content','children'),Input('url','pathname'))defrender_page_content(pathname):ifpathname=='/':returnindex_pageelifpathname=='/age':returnage_pageelifpathname=='/sex':returnsex_pageelifpathname=='/statistics':returnstatistics_pagereturnhtml.H1('您访问的页面不存在!')2.2.4在views子模块中构建多页面前端内容在上一小节的路由回调中你可能会好奇不同url下的返回值index_page、age_page等都是什么,这些都构建在子模块views下:
+views/age.pyindex.pysex.pystatistics.py__init__.py譬如其中之一的age.py内容如下:
fromviews.indeximportindex_pagefromviews.ageimportage_pagefromviews.seximportsex_pagefromviews.statisticsimportstatistics_page2.2.5在callbacks子模块中构建多页面后端逻辑当你在views下构建的页面内容中涉及到回调交互的功能时,我推荐将对应的后端回调逻辑拆分到callbacks子模块下同名文件中,这样非常便于编写与维护。
同时一定要记住在views下对应的前端子模块中,一定要导入callbacks中对应的回调子模块内部的至少一个对象,否则Dash在打包应用时是扫描不到相应的回调函数内容进行编译的,进而会导致应用启动时回调无效,譬如在views/statistics.py中我们就执行了fromcallbacks.statisticsimportstatistics_data。
前面说的很多内容都关乎Dash应用的构建,而当你的Dash应用依赖外部数据时,推荐的方式是类似flask项目那样构建子模块models来定义数据模型,实现与数据库的关联。
frompeeweeimportSqliteDatabase,ModelfrompeeweeimportCharField,FloatFielddb=SqliteDatabase('models/age.db')classAge(Model):#地区,唯一region=CharField(unique=True)#0-14岁占比prop_0_to_14=FloatField()#15-59岁占比prop_15_59=FloatField()#60岁及以上占比prop_60_above=FloatField()#65岁及以上占比prop_65_above=FloatField()classMeta:database=dbprimary_key=False#禁止自动生成唯一id列@classmethoddeffetch_all(cls):returnlist(cls.select().dicts())而本文案例中涉及到的数据可视化内容均由plotly及plotly.express实现,关于这部分内容我会在之后的进阶教程中加以概括。
下期我将带大家学习如何在Linux、Windows等系统中正式部署Dash应用,敬请期待。