Python+Dash快速web應(yīng)用開發(fā)——基礎(chǔ)概念篇

?本文示例代碼與數(shù)據(jù)已上傳至我的
?Github倉庫https://github.com/CNFeffery/DataScienceStudyNotes
1 簡介
這是我的新系列教程「Python+Dash快速web應(yīng)用開發(fā)」的第一期,我們都清楚學(xué)習(xí)一個新工具需要一定的動力,那么為什么我要專門為Dash制作一個系列教程呢?

Dash是一個高效簡潔的Python框架,建立在Flask、Poltly.js以及React.js的基礎(chǔ)上,設(shè)計之初是為了幫助「前端知識匱乏」的數(shù)據(jù)分析人員,以純Python編程的方式快速開發(fā)出交互式的數(shù)據(jù)可視化web應(yīng)用。
Dash已經(jīng)過數(shù)年的迭代發(fā)展,早期的Dash我也體驗過,但當(dāng)時還比較簡陋,很多問題亟待解決,因此并沒有引起我的多大注意。
但隨著近一兩年的高速發(fā)展和積極更新迭代,現(xiàn)階段的Dash已經(jīng)是一個相當(dāng)成熟的框架,且其功能已經(jīng)豐富到不僅僅可以用來開發(fā)在線數(shù)據(jù)可視化作品,即使是輕量級的數(shù)據(jù)儀表盤、BI應(yīng)用,甚至是搭建文檔說明、博客或常規(guī)的網(wǎng)站,都駕馭得住,配合豐富的第三方拓展,只會Python的你可以開發(fā)出相當(dāng)精美正式的web應(yīng)用。

而關(guān)于Dash的像樣的中文教程幾乎沒有(其實英文教程也沒多少??),有的也大多只是在照搬官方文檔,因此類似之前寫作完成反響不錯的geopandas教程那樣,我來寫一個看得過去的系列教程吧~下面開始我們的Dash之旅吧!
2?Dash中的基礎(chǔ)概念
在學(xué)習(xí)Dash的一開始,我們需要對Dash的若干基礎(chǔ)概念進(jìn)行了解,首先我們來從頭開始搭建Dash環(huán)境,因為主要是面向數(shù)據(jù)分析處理人員,所以我推薦使用conda進(jìn)行環(huán)境管理,參考下列命令即可完成環(huán)境的初始化:
conda?create?-n?dash-dev?python=3.7?-y
conda?activate?dash-dev
pip?install?dash?-U
上述代碼執(zhí)行完成后,你就已經(jīng)創(chuàng)建好最基本的Dash運行所需環(huán)境了,你可以創(chuàng)建代碼如下的py腳本并執(zhí)行(推薦使用pycharm、vscode等工具進(jìn)行Dash開發(fā)):
?app1.py
?
import?dash
import?dash_html_components?as?html
app?=?dash.Dash(__name__)
app.layout?=?html.H1('第一個Dash應(yīng)用!')
if?__name__?==?'__main__':
????app.run_server()
運行上述腳本之后,一切正常的話,按照提示點擊進(jìn)對應(yīng)網(wǎng)址會看到如下內(nèi)容:

至此我們就完成了Dash環(huán)境的搭建,下面我們來了解Dash應(yīng)用中的一些基礎(chǔ)概念:
2.1?用layout設(shè)計頁面內(nèi)容
一個web應(yīng)用的關(guān)鍵之一在于其前端所呈現(xiàn)的頁面內(nèi)容,在Dash中我們通過對其layout屬性進(jìn)行定義,從而自由設(shè)計頁面內(nèi)容。
在前面的app1.py中,我們設(shè)置了app.layout = html.H1('第一個Dash應(yīng)用!'),這里的html即開頭導(dǎo)入的dash_html_components,它是dash的自帶依賴庫,用于在Dash應(yīng)用中定義常見的html元素,就像前面用到的H1對應(yīng)一級標(biāo)題,即標(biāo)簽。
而每個html.XX對象,其接收的第一個位置上的參數(shù)都是children,它用于表示對應(yīng)html標(biāo)簽所包裹的內(nèi)容,譬如上文的'第一個Dash應(yīng)用!',也可以通過傳入多元素列表或進(jìn)行多層嵌套,從而構(gòu)建結(jié)構(gòu)更復(fù)雜的頁面內(nèi)容,就像下面的例子一樣:
?app2.py
?
import?dash
import?dash_html_components?as?html
app?=?dash.Dash(__name__)
app.layout?=?html.Div(
????[
????????html.H1('標(biāo)題1'),
????????html.H1('標(biāo)題2'),
????????html.P(['測試',?html.Br(),?'測試']),
????????html.Table(
????????????html.Tr(
????????????????[
????????????????????html.Td('第一列'),
????????????????????html.Td('第二列')
????????????????]
????????????)
????????)
????]
)
if?__name__?==?'__main__':
????app.run_server()

而除了常見的html元素之外,Dash還在其官方依賴庫dash_core_components中內(nèi)置了眾多常見網(wǎng)頁小部件,是我們實現(xiàn)交互式所依托的重要元素,就像下面的例子一樣我們利用其Dropdown部件創(chuàng)建出一個下拉選擇部件:
?app3.py
?
import?dash
import?dash_html_components?as?html
import?dash_core_components?as?dcc
app?=?dash.Dash(__name__)
app.layout?=?html.Div(
????[
????????html.H1('下拉選擇'),
????????html.Br(),
????????dcc.Dropdown(
????????????options=[
????????????????{'label':?'選項一',?'value':?1},
????????????????{'label':?'選項二',?'value':?2},
????????????????{'label':?'選項三',?'value':?3}
????????????]
????????)
????]
)
if?__name__?==?'__main__':
????app.run_server()

Dash與plotly既然“師出同門”,自然已經(jīng)相互打通,我們同樣可以非常輕松的在網(wǎng)頁中插入數(shù)據(jù)可視化的內(nèi)容,這里我們使用到plotly.express,它簡化了諸多plotly圖表的創(chuàng)建過程,將創(chuàng)建好的圖表對象作為figure參數(shù)傳入dcc.Graph()中即可:
?app4.py
?
import?dash
import?dash_html_components?as?html
import?dash_core_components?as?dcc
import?plotly.express?as?px
app?=?dash.Dash(__name__)
fig?=?px.scatter(x=range(10),?y=range(10))
app.layout?=?html.Div(
????[
????????html.H1('嵌入plotly圖表'),
????????dcc.Graph(figure=fig)
????]
)
if?__name__?==?'__main__':
????app.run_server()

除了上述的幾個官方Dash依賴庫以外,還有很多優(yōu)秀的第三方庫都可以幫助我們快速創(chuàng)建出效果驚人的前端內(nèi)容,關(guān)于這部分的詳細(xì)內(nèi)容我將會在本系列之后的文章中分主題詳細(xì)介紹,敬請期待。
2.2?用callback實現(xiàn)交互
Dash最大的優(yōu)點之一就是其高度封裝了React.js,使得我們無需編寫js代碼即可實現(xiàn)前端與后端之間的異步交互,為了實現(xiàn)這一步,我們需要使用到dash.dependencies中的Input與Output,再配合自定義回調(diào)函數(shù)來實現(xiàn)所需交互功能。
舉一個非常簡單的例子:我們設(shè)計一個web頁面,其中有一個「下拉選項」部件,當(dāng)我們下拉選取到某個選項值對應(yīng)的省份時,其下方打印出對應(yīng)的省會城市:
?app5.py
?
import?dash
import?dash_html_components?as?html
import?dash_core_components?as?dcc
from?dash.dependencies?import?Input,?Output
app?=?dash.Dash(__name__)
app.layout?=?html.Div(
????[
????????html.H1('根據(jù)省名查詢省會城市:'),
????????html.Br(),
????????dcc.Dropdown(
????????????id='province',
????????????options=[
????????????????{'label':?'四川省',?'value':?'四川省'},
????????????????{'label':?'陜西省',?'value':?'陜西省'},
????????????????{'label':?'廣東省',?'value':?'廣東省'}
????????????],
????????????value='四川省'
????????),
????????html.P(id='city')
????]
)
province2city_dict?=?{
????'四川省':?'成都市',
????'陜西省':?'西安市',
????'廣東省':?'廣州市'
}
@app.callback(Output('city',?'children'),
??????????????Input('province',?'value'))
def?province2city(province):
????return?province2city_dict[province]
if?__name__?==?'__main__':
????app.run_server()

在交互操作的時候查看后臺可以看到,每一次點選都在進(jìn)行與后臺的「異步通信」,我們整個應(yīng)用的頁面并沒有刷新,如果不用Dash,你就得書寫相應(yīng)的js語句,較為繁瑣:

而Dash目前已經(jīng)支持「多輸入多輸出」的回調(diào)函數(shù)書寫方式,以及「阻止初次回調(diào)」、「基于表單提交狀態(tài)的回調(diào)」等諸多特性,理論上你可以創(chuàng)建出任何形式的頁面交互行為,這些內(nèi)容我們都會在之后的系列文章中詳細(xì)教授給大家。
2.3 監(jiān)聽圖表交互式選擇行為
Dash與plotly的高度耦合,還體現(xiàn)在其可以監(jiān)聽針對plotly圖表的懸浮、選擇、框選等行為,廣泛適用于plotly中的大量常規(guī)圖表與地圖,這一點懂的朋友應(yīng)該都明白,借助這個特性,我們可以創(chuàng)建出交互能力強大的web應(yīng)用,就像我下面的這個典型的例子:
?app6.py
?
import?dash
import?dash_core_components?as?dcc
import?dash_html_components?as?html
from?dash.dependencies?import?Input,?Output
import?plotly.express?as?px
app?=?dash.Dash(__name__)
fig?=?px.scatter(x=range(10),?y=range(10),?height=400)
fig.update_layout(clickmode='event+select')??#?設(shè)置點擊模式
app.layout?=?html.Div(
????[
????????dcc.Graph(figure=fig,?id='scatter'),
????????html.Hr(),
????????html.Div([
????????????'懸浮事件:',
????????????html.P(id='hover')
????????]),
????????html.Hr(),
????????html.Div([
????????????'點擊事件:',
????????????html.P(id='click')
????????]),
????????html.Hr(),
????????html.Div([
????????????'選擇事件:',
????????????html.P(id='select')
????????]),
????????html.Hr(),
????????html.Div([
????????????'框選事件:',
????????????html.P(id='zoom')
????????])
????]
)
#?多對多的回調(diào)函數(shù)
@app.callback([Output('hover',?'children'),
???????????????Output('click',?'children'),
???????????????Output('select',?'children'),
???????????????Output('zoom',?'children'),],
??????????????[Input('scatter',?'hoverData'),
???????????????Input('scatter',?'clickData'),
???????????????Input('scatter',?'selectedData'),
???????????????Input('scatter',?'relayoutData')])
def?listen_to_hover(hoverData,?clickData,?selectedData,?relayoutData):
????return?str(hoverData),?str(clickData),?str(selectedData),?str(relayoutData)
if?__name__?==?'__main__':
????app.run_server()
可以看到,我們監(jiān)聽到的懸浮、點擊、選擇以及框選四種行為對應(yīng)傳回的特征數(shù)據(jù):

而這方面內(nèi)容,我也會在之后的系列文章中進(jìn)行非常詳實的介紹??~
我們接下來的系列文章就會圍繞上述基礎(chǔ)概念,以及「多頁面應(yīng)用」、「外部css、js的引入」、「Dash應(yīng)用的部署發(fā)布」等還未提及的重要內(nèi)容進(jìn)行詳細(xì)介紹,以幫助廣大使用Python的讀者朋友使用最少的前端知識,創(chuàng)建出優(yōu)秀的web應(yīng)用,方便日常的工作學(xué)習(xí)生產(chǎn)生活,敬請期待!
以上就是本文的全部內(nèi)容,歡迎在評論區(qū)與我進(jìn)行討論~

加入我們的知識星球【我們談?wù)摂?shù)據(jù)科學(xué)】
愛上數(shù)據(jù)分析!
·?推薦閱讀?·

