本文示例代碼已上傳至我的
Github倉庫https://github.com/CNFeffery/DataScienceStudyNotes
1 簡介
這是我的系列教程Python+Dash快速web應用開發的第二期,在上一期中,我帶領大家認識了什么是Dash,Dash可以做什么,以及Dash中最基本的一些概念,而今天開始,我將開始帶領大家正式學習有關Dash的實用知識,以及各種奇淫巧技😋~
今天的文章,我將帶大家學習Dash中頁面布局的先進方法,通過今天的文章,你將學會以非常簡單的方式實現現代化的頁面布局,下面讓我們開始吧~
2 為Dash應用設計頁面布局
我們都知道,一個好的網頁設計通常都需要編寫css甚至js來定制前端內容,譬如非常流行的bootstrap框架。
但我們既然想使用Dash來搭建web應用,很大的一個原因是不熟悉或者不想寫繁瑣的前端代碼,而Dash的第三方拓展庫中就有這么一個Python庫——dash-bootstrap-components,借助它,我們就可以純Python編程調用到 bootstrap框架中的諸多特性來讓我們的web應用頁面更美觀。
首先需要通過pip install dash-bootstrap-components來安裝它,安裝完成之后,我們來驗證一下是否可以正常使用,推薦以import dash_bootstrap_components as dbc的方式導入:
app1.py
import dash
import dash_bootstrap_components as dbc
app = dash.Dash(
__name__,
# 從國內可順暢訪問的cdn獲取所需的原生bootstrap對應css
external_stylesheets=['https://cdn.staticfile.org/twitter-bootstrap/4.5.2/css/bootstrap.min.css']
)
app.layout = dbc.Alert(
"你好,dash_bootstrap_components!", color='success'
)
if __name__ == "__main__":
app.run_server()
執行后打開所提示的網址,看到下列信息就說明安裝成功:
這里我們使用到dash.Dash()中的參數external_stylesheets,用於引入外部的css文件,有了這些補充進來的css,我們才得以實現更多彩的樣式,而除了上述填入url的方式之外,我更推薦的方式是在我們的Dash應用.py文件同級目錄創建文件夾assets,放在這個目錄中的文件會被Dash自動掃描到,也就無需填入external_stylesheets參數啦:
app2.py
import dash
import dash_bootstrap_components as dbc
app = dash.Dash(__name__)
app.layout = dbc.Alert(
"你好,dash_bootstrap_components!", color='success'
)
if __name__ == "__main__":
app.run_server()
這時在Dash頁面抓包可以看到對應bootstrap.min.css的url信息指向域名下的對應目錄:
這種方式最穩妥,不受網絡波動影響,推薦大家養成好習慣。
在測試完dash-bootstrap-components的可用性之后,接下來我們就開始學習構造頁面布局。
2.1 認識Container()、Row()與Col()
- Container()
dash-bootstrap-components封裝了bootstrap框架中的網格系統,我們在使用它進行布局時,首先要了解的是組件Container(),它是我們組織頁面元素的容器,其參數fluid默認為False,會以兩邊填充空白區域的方式居中其內部嵌套的子元素:
app3.py
import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div(
[
# fluid默認為False
dbc.Container(
[
dcc.Dropdown(),
'測試',
dcc.Dropdown()
]
),
html.Hr(), # 水平分割線
# fluid設置為True
dbc.Container(
[
dcc.Dropdown(),
'測試',
dcc.Dropdown()
],
fluid=True
)
]
)
if __name__ == "__main__":
app.run_server()
可以看到,第一個Container()部分呈現出兩邊空白填充中間居中的形式,而第二個則充滿了整個水平方向。
- Row()與Col()
在上面所介紹的Container()之內,我們就可以按照bootstrap的網格系統進行內容的排布:行嵌套列,再向列內嵌套各種部件。
而所謂的網格系統指的是每個Row()部件內部分成寬度相等的12份,傳入的Col()部件具有參數width可以傳入整數來分配對應數量的寬度,如下例:
app4.py
import dash
import dash_bootstrap_components as dbc
app = dash.Dash(__name__)
app.layout = dbc.Container(
[
dbc.Row(dbc.Col('第一行'),
style={
'background-color': 'lightgreen'
}),
dbc.Row(
[
dbc.Col('第二行第一列', width=6, style={'background-color': 'lightblue'}),
dbc.Col('第二行第二列', width=6, style={'background-color': 'lightskyblue'})
]
),
dbc.Row(
[
dbc.Col('第三行第一列', width=2, style={'background-color': 'HotPink'}),
dbc.Col('第三行第二列', width=10, style={'background-color': 'IndianRed'})
]
),
dbc.Row(
[
dbc.Col('第四行第一列', width=2, style={'background-color': 'HotPink'}),
dbc.Col('第四行第二列', width=2, style={'background-color': 'IndianRed'}),
dbc.Col('第四行第三列', width=2, style={'background-color': 'HotPink'})
]
),
dbc.Row(
[
dbc.Col('第五行第一列', width=2, style={'background-color': 'LightSteelBlue'}),
dbc.Col('第五行第二列', width=11, style={'background-color': 'MistyRose'}),
]
)
]
)
if __name__ == "__main__":
app.run_server()
可以看到當Row()部件下所有Col()部件寬度之和為12時是正好充滿的,當寬度之和不足12時剩余的寬度會被空出來,而寬度之和若大於12,則會把導致寬度溢出的Col()部件擠到下一行中,所以我們在利用這種網格系統排布網頁元素時要注意規范。
而行部件也是可以嵌套到上一級列部件中的,因此如果你覺得12份不夠自己實現更精確的寬度分配,就可以寫個嵌套,實現固定寬度下再次划分12份,就像下面例子中我們:
app5.py
import dash
import dash_bootstrap_components as dbc
app = dash.Dash(__name__)
app.layout = dbc.Container(
[
dbc.Row(dbc.Col('第一行'),
style={
'background-color': 'lightgreen'
}),
dbc.Row(
[
dbc.Col('第二行第一列', width=6, style={'background-color': 'lightblue'}),
dbc.Col(
dbc.Row(
[
dbc.Col('嵌套1', width=6, style={'background-color': 'Moccasin'}),
dbc.Col('嵌套2', width=3, style={'background-color': 'lightskyblue'}),
dbc.Col('嵌套3', width=3, style={'background-color': 'Moccasin'}),
]
),
width=6,
style={'background-color': 'lightskyblue'})
]
)
]
)
if __name__ == "__main__":
app.run_server()
在get到這一小節的知識點后,我們就可以更規矩地編寫頁面內容,譬如寫出下面這樣的調查問卷就比較輕松(受限於篇幅,下面例子對應的app6.py不便放出代碼,你可以在文章開頭的Github倉庫對應路徑找到它):
app6.py
2.2 Row()與Col()部件的進階設置
通過上一小節的例子,想必你已經學習到如何在Dash中編排出bootstrap網格系統風格的頁面,而為了在已初步編排好的網頁基礎上做更多實用優化,dash-bootstrap-components還為Row()與Col()部件提供了一些微調布局的參數:
- 利用order設定順序
我們在前面為Col()部件所設定的width參數都只是1到12之間的整數,其實它還可以接受字典輸入,從而拓展其功能,原先的整數寬度輸入就由width=n轉化為width={'size': n}。
除此之外,我們還可以添加order鍵參數來為同一個Row()下的部件設置順序,接受三種輸入:'first'表示置於當前行第一列,'last'表示置於當前行最后一列,而1到12的整數則可以直接以序號編排列部件順序。
結合下面這個簡單的例子理解這部分內容:
app7.py
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div(
dbc.Container(
[
html.Br(),
html.Br(),
html.Br(),
dbc.Row(
[
dbc.Col('1', width=2, style={'background-color': 'lightblue'}),
dbc.Col('2', width=2, style={'background-color': 'lightskyblue'}),
dbc.Col('3', width=2, style={'background-color': '#e88b00'}),
dbc.Col('4', width=2, style={'background-color': '#8c8c8c'})
]
),
html.Br(),
dbc.Row(
[
dbc.Col('order=last', width={'size': 2, 'order': 'last'}, style={'background-color': 'lightblue'}),
dbc.Col('order=2', width={'size': 2, 'order': 2}, style={'background-color': 'lightskyblue'}),
dbc.Col('order=1', width={'size': 2, 'order': 1}, style={'background-color': '#e88b00'}),
dbc.Col('order=first', width={'size': 2, 'order': 'first'}, style={'background-color': '#8c8c8c'})
]
)
]
)
)
if __name__ == '__main__':
app.run_server()
可以很直觀地看出order參數對列部件順序的影響:
- 利用offset設置偏移
列部件的width參數字典中還可以使用鍵值對參數offset,傳入1到12的整數,它的作用是為對應的Col()部件左側增加對應寬度的位移,就像下面的例子一樣:
app8.py
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
app = dash.Dash__name__)
app.layout = html.Div(
dbc.Container(
[
html.Br(),
html.Br(),
html.Br(),
dbc.Row(
[
dbc.Col('1', width=2, style={'background-color': 'lightblue'}),
dbc.Col('2', width=2, style={'background-color': 'lightskyblue'}),
dbc.Col('3', width=2, style={'background-color': '#e88b00'}),
dbc.Col('4', width=2, style={'background-color': '#8c8c8c'})
],
style={'border': '1px solid black'}
),
html.Br(),
dbc.Row(
[
dbc.Col('offset=1', width={'size': 2, 'offset': 1}, style={'background-color': 'lightblue'}),
dbc.Col('offset=2', width={'size': 2, 'offset': 2}, style={'background-color': 'lightskyblue'}),
dbc.Col('3', width=2, style={'background-color': '#e88b00'}),
dbc.Col('offset=1', width={'size': 2, 'offset': 1}, style={'background-color': '#8c8c8c'})
],
style={'border': '1px solid black'}
)
]
)
)
if __name__ == '__main__':
app.run_server()
為了更明顯,我給每個Row()部件加了輪廓線,可以看到效果非常直觀:
- 設置水平對齊方式
在前面的內容中,我們在同一個Row()部件下組織的所有Col()部件,其順序都是從左到右一個緊貼下一個排布的,即使設置了offset參數,也只是插空后緊貼。
但在很多頁面布局需求中需要對於同一行的多個列元素設置對齊方式,這在dash-bootstrap-components中可以通過對Row()部件設置參數justify來實現,可選項有'start'、'center'、'end'、'between'以及'around'五種,每種產生的效果如下面的例子:
app9.py
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div(
dbc.Container(
[
html.Br(),
html.Br(),
html.Br(),
dbc.Row(
[
dbc.Col('start', width=3, style={'border': '1px solid black'}),
dbc.Col('start', width=3, style={'border': '1px solid black'}),
dbc.Col('start', width=3, style={'border': '1px solid black'})
],
justify='start'
),
html.Br(),
dbc.Row(
[
dbc.Col('center', width=3, style={'border': '1px solid black'}),
dbc.Col('center', width=3, style={'border': '1px solid black'}),
dbc.Col('center', width=3, style={'border': '1px solid black'})
],
justify='center'
),
html.Br(),
dbc.Row(
[
dbc.Col('end', width=3, style={'border': '1px solid black'}),
dbc.Col('end', width=3, style={'border': '1px solid black'}),
dbc.Col('end', width=3, style={'border': '1px solid black'})
],
justify='end'
),
html.Br(),
dbc.Row(
[
dbc.Col('between', width=3, style={'border': '1px solid black'}),
dbc.Col('between', width=3, style={'border': '1px solid black'}),
dbc.Col('between', width=3, style={'border': '1px solid black'})
],
justify='between'
),
html.Br(),
dbc.Row(
[
dbc.Col('around', width=3, style={'border': '1px solid black'}),
dbc.Col('around', width=3, style={'border': '1px solid black'}),
dbc.Col('around', width=3, style={'border': '1px solid black'})
],
justify='around'
)
],
# 為Container兩邊添加參考線
style={'border-left': '1px solid red', 'border-right': '1px solid red'}
)
)
if __name__ == '__main__':
app.run_server()
2.3 實際案例
通過對上面知識內容的學習,我們掌握了如何基於拓展庫dash-bootstrap-components,在Dash中實現bootstrap的網格系統。
下面我們來利用今天學到的知識點,搭建下圖所示的登錄頁面,其中涉及到一些還未給大家介紹的知識點,但很簡單,之后的課程會介紹,而涉及到一些額外的css的內容我都已寫好注釋非常簡單~
對應代碼如下:
app10.py
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
app = dash.Dash(__name__)
app.layout = html.Div(
[
html.Br(),
html.Br(),
html.Br(),
html.Br(),
html.Br(),
html.Br(),
html.Br(),
html.Br(),
dbc.Container(
[
dbc.Row(style={'height': '30px'}), # 利用css設置高度
dbc.Row(
dbc.Col('Email address')
),
dbc.Row(
dbc.Col(dbc.Input(placeholder='Enter email'))
),
dbc.Row(
dbc.Col('Password')
),
dbc.Row(
dbc.Col(dbc.Input(placeholder='Enter Password'))
),
dbc.Row(
dbc.Col(
[
'By signing up you accept our ',
html.A('Terms Of Use', href='#')
],
width={'size': 10, 'offset': 1},
style={'text-align': 'center'} # 利用css設置文字居中
),
style={'margin': '6px'} # 利用css設置上下留白高度
),
dbc.Row(
dbc.Col(
# 利用css實現圓角矩形效果
dbc.Button('LOGIN', style={'border-radius': '18px'}, block=True),
width={'size': 8, 'offset': 2},
style={'text-align': 'center'}
)
),
dbc.Row(
[
dbc.Col(html.Hr()),
html.P('or', style={'text-align': 'center', 'margin': 0}),
dbc.Col(html.Hr())
]
),
dbc.Row(
dbc.Col(
dbc.Button(
'Signup using Google',
style={'border-radius': '18px'},
block=True,
outline=True
),
width={'size': 8, 'offset': 2},
style={'text-align': 'center'}
)
),
dbc.Row(
dbc.Col(
[
"Don't have account? ",
html.A('Sign up here', href='#')
],
width={'size': 10, 'offset': 1},
style={'text-align': 'center'}
),
style={'margin': '6px'}
),
html.Br(),
],
style={
'background-color': '#ededef', # 設置背景顏色
'max-width': '480px', # 為Container部件設置最大寬度
'border-radius': '12px'
}
)
]
)
if __name__ == '__main__':
app.run_server()
以上就是本文的全部內容,歡迎在評論區與我進行討論,點贊越多下一期更新越快哦😋~
