Python+Dash快速web应用开发——页面布局篇

本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes

1 简介

这是我的系列教程「Python+Dash快速web应用开发」的第二期,在上一期中,我带领大家认识了什么是DashDash可以做什么,以及Dash中最基本的一些概念,而今天开始,我将开始带领大家正式学习有关Dash的实用知识,以及各种奇淫巧技????~

 图1

今天的文章,我将带大家学习Dash「页面布局」的先进方法,通过今天的文章,你将学会以非常简单的方式实现现代化的页面布局,下面让我们开始吧~

2 为Dash应用设计页面布局

我们都知道,一个好的网页设计通常都需要编写css甚至js来定制前端内容,譬如非常流行的bootstrap框架。

 图2

但我们既然想使用Dash来搭建web应用,很大的一个原因是不熟悉或者不想写繁琐的前端代码,而Dash的第三方拓展库中就有这么一个Python库——dash-bootstrap-components,借助它,我们就可以纯Python编程调用到 bootstrap框架中的诸多特性来让我们的web应用页面更美观。

首先需要通过pip install dash-bootstrap-components来安装它,安装完成之后,我们来验证一下是否可以正常使用,推荐以import dash_bootstrap_components as dbc的方式导入:

app1.py

 
  1. import dash

  2. import dash_bootstrap_components as dbc

  3.  
  4. app = dash.Dash(

  5.     __name__,

  6.     # 从国内可顺畅访问的cdn获取所需的原生bootstrap对应css

  7.     external_stylesheets=['https://cdn.staticfile.org/twitter-bootstrap/4.5.2/css/bootstrap.min.css']

  8. )

  9.  
  10. app.layout = dbc.Alert(

  11.     "你好,dash_bootstrap_components!"

  12. )

  13.  
  14. if __name__ == "__main__":

  15.     app.run_server()

执行后打开所提示的网址,看到下列信息就说明安装成功:

 图3

这里我们使用到dash.Dash()中的参数external_stylesheets,用于引入外部的css文件,有了这些补充进来的css,我们才得以实现更多彩的样式,而除了上述填入url的方式之外,我更推荐的方式是在我们的Dash应用.py文件同级目录创建文件夹assets,放在这个目录中的文件会被Dash自动扫描到:

app2.py

 
  1. import dash

  2. import dash_bootstrap_components as dbc

  3.  
  4. app = dash.Dash(

  5.     __name__,

  6.     # 直接填写assets下css文件路径+文件名

  7.     external_stylesheets=['css/bootstrap.min.css']

  8. )

  9.  
  10. app.layout = dbc.Alert(

  11.     "你好,dash_bootstrap_components!"

  12. )

  13.  
  14. if __name__ == "__main__":

  15.     app.run_server()

 图4

这时在Dash页面抓包可以看到对应bootstrap.min.css的url信息指向域名下的对应目录:

 图5

这种方式最稳妥,不受网络波动影响,推荐大家养成好习惯。

在测试完dash-bootstrap-components的可用性之后,接下来我们就开始学习构造页面布局。

2.1 认识Container()、Row()与Col()

  • 「Container()」

dash-bootstrap-components封装了bootstrap框架中的「网格系统」,我们在使用它进行布局时,首先要了解的是组件Container(),它是我们组织页面元素的容器,其参数fluid默认为False,会以两边填充空白区域的方式居中其内部嵌套的子元素:

app3.py

 
  1. import dash

  2. import dash_bootstrap_components as dbc

  3. import dash_core_components as dcc

  4. import dash_html_components as html

  5.  
  6. app = dash.Dash(

  7.     __name__,

  8.     external_stylesheets=['css/bootstrap.min.css']

  9. )

  10.  
  11. app.layout = html.Div(

  12.     [

  13.         # fluid默认为False

  14.         dbc.Container(

  15.             [

  16.                 dcc.Dropdown(),

  17.                 '测试',

  18.                 dcc.Dropdown()

  19.             ]

  20.         ),

  21.  
  22.         html.Hr(), # 水平分割线

  23.  
  24.         # fluid设置为True

  25.         dbc.Container(

  26.             [

  27.                 dcc.Dropdown(),

  28.                 '测试',

  29.                 dcc.Dropdown()

  30.             ],

  31.             fluid=True

  32.         )

  33.     ]

  34. )

  35.  
  36. if __name__ == "__main__":

  37.     app.run_server()

 图6

可以看到,第一个Container()部分呈现出两边空白填充中间居中的形式,而第二个则充满了整个水平方向。

  • 「Row()与Col()」

在上面所介绍的Container()之内,我们就可以按照bootstrap的网格系统进行内容的排布:「行」嵌套「列」,再向「列」内嵌套各种部件。

而所谓的网格系统指的是每个Row()部件内部分成宽度相等的「12」份,传入的Col()部件具有参数width可以传入「整数」来分配对应数量的宽度,如下例:

app4.py

 
  1. import dash

  2. import dash_bootstrap_components as dbc

  3.  
  4. app = dash.Dash(

  5.     __name__,

  6.     external_stylesheets=['css/bootstrap.min.css']

  7. )

  8.  
  9. app.layout = dbc.Container(

  10.     [

  11.         dbc.Row(dbc.Col('第一行'),

  12.                 style={

  13.                     'background-color': 'lightgreen'

  14.                 }),

  15.         dbc.Row(

  16.             [

  17.                 dbc.Col('第二行第一列', width=6, style={'background-color': 'lightblue'}),

  18.                 dbc.Col('第二行第二列', width=6, style={'background-color': 'lightskyblue'})

  19.             ]

  20.         ),

  21.         dbc.Row(

  22.             [

  23.                 dbc.Col('第三行第一列', width=2, style={'background-color': 'HotPink'}),

  24.                 dbc.Col('第三行第二列', width=10, style={'background-color': 'IndianRed'})

  25.             ]

  26.         ),

  27.         dbc.Row(

  28.             [

  29.                 dbc.Col('第四行第一列', width=2, style={'background-color': 'HotPink'}),

  30.                 dbc.Col('第四行第二列', width=2, style={'background-color': 'IndianRed'}),

  31.                 dbc.Col('第四行第三列', width=2, style={'background-color': 'HotPink'})

  32.             ]

  33.         ),

  34.         dbc.Row(

  35.             [

  36.                 dbc.Col('第五行第一列', width=2, style={'background-color': 'LightSteelBlue'}),

  37.                 dbc.Col('第五行第二列', width=11, style={'background-color': 'MistyRose'}),

  38.             ]

  39.         )

  40.     ]

  41. )

  42.  
  43. if __name__ == "__main__":

  44.     app.run_server()

 图7

可以看到当Row()部件下所有Col()部件宽度之和为12时是正好充满的,当宽度之和不足12时剩余的宽度会被空出来,而宽度之和若大于12,则会把导致宽度溢出的Col()部件挤到下一行中,所以我们在利用这种网格系统排布网页元素时要注意规范。

「行部件」也是可以嵌套到上一级「列部件」中的,因此如果你觉得12份不够自己实现更精确的宽度分配,就可以写个嵌套,实现固定宽度下再次划分12份,就像下面例子中我们:

app5.py

 
  1. import dash

  2. import dash_bootstrap_components as dbc

  3.  
  4. app = dash.Dash(

  5.     __name__,

  6.     external_stylesheets=['css/bootstrap.min.css']

  7. )

  8.  
  9. app.layout = dbc.Container(

  10.     [

  11.         dbc.Row(dbc.Col('第一行'),

  12.                 style={

  13.                     'background-color': 'lightgreen'

  14.                 }),

  15.         dbc.Row(

  16.             [

  17.                 dbc.Col('第二行第一列', width=6, style={'background-color': 'lightblue'}),

  18.                 dbc.Col(

  19.                     dbc.Row(

  20.                         [

  21.                             dbc.Col('嵌套1', width=6, style={'background-color': 'Moccasin'}),

  22.                             dbc.Col('嵌套2', width=3, style={'background-color': 'lightskyblue'}),

  23.                             dbc.Col('嵌套3', width=3, style={'background-color': 'Moccasin'}),

  24.                         ]

  25.                     ),

  26.                     width=6,

  27.                     style={'background-color': 'lightskyblue'})

  28.             ]

  29.         )

  30.     ]

  31. )

  32.  
  33. if __name__ == "__main__":

  34.     app.run_server()

 图8

在get到这一小节的知识点后,我们就可以更规矩地编写页面内容,譬如写出下面这样的调查问卷就比较轻松(受限于篇幅,下面例子对应的app6.py不便放出代码,你可以在文章开头的Github仓库对应路径找到它):

app6.py

 图9

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

 
  1. import dash

  2. import dash_bootstrap_components as dbc

  3. import dash_html_components as html

  4.  
  5. app = dash.Dash(

  6.     __name__,

  7.     external_stylesheets=['css/bootstrap.min.css']

  8. )

  9.  
  10. app.layout = html.Div(

  11.     dbc.Container(

  12.         [

  13.             html.Br(),

  14.             html.Br(),

  15.             html.Br(),

  16.             dbc.Row(

  17.                 [

  18.                     dbc.Col('1', width=2, style={'background-color': 'lightblue'}),

  19.                     dbc.Col('2', width=2, style={'background-color': 'lightskyblue'}),

  20.                     dbc.Col('3', width=2, style={'background-color': '#e88b00'}),

  21.                     dbc.Col('4', width=2, style={'background-color': '#8c8c8c'})

  22.                 ]

  23.             ),

  24.             html.Br(),

  25.             dbc.Row(

  26.                 [

  27.                     dbc.Col('order=last', width={'size': 2, 'order': 'last'}, style={'background-color': 'lightblue'}),

  28.                     dbc.Col('order=2', width={'size': 2, 'order': 2}, style={'background-color': 'lightskyblue'}),

  29.                     dbc.Col('order=1', width={'size': 2, 'order': 1}, style={'background-color': '#e88b00'}),

  30.                     dbc.Col('order=first', width={'size': 2, 'order': 'first'}, style={'background-color': '#8c8c8c'})

  31.                 ]

  32.             )

  33.         ]

  34.     )

  35. )

  36.  
  37. if __name__ == '__main__':

  38.     app.run_server()

可以很直观地看出order参数对列部件顺序的影响:

 图10

  • 「利用offset设置偏移」

列部件的width参数字典中还可以使用键值对参数offset,传入1到12的整数,它的作用是为对应的Col()部件左侧增加对应宽度的位移,就像下面的例子一样:

app8.py

 
  1. import dash

  2. import dash_bootstrap_components as dbc

  3. import dash_html_components as html

  4.  
  5. app = dash.Dash(

  6.     __name__,

  7.     external_stylesheets=['css/bootstrap.min.css']

  8. )

  9.  
  10. app.layout = html.Div(

  11.     dbc.Container(

  12.         [

  13.             html.Br(),

  14.             html.Br(),

  15.             html.Br(),

  16.             dbc.Row(

  17.                 [

  18.                     dbc.Col('1', width=2, style={'background-color': 'lightblue'}),

  19.                     dbc.Col('2', width=2, style={'background-color': 'lightskyblue'}),

  20.                     dbc.Col('3', width=2, style={'background-color': '#e88b00'}),

  21.                     dbc.Col('4', width=2, style={'background-color': '#8c8c8c'})

  22.                 ],

  23.                 style={'border': '1px solid black'}

  24.             ),

  25.             html.Br(),

  26.             dbc.Row(

  27.                 [

  28.                     dbc.Col('offset=1', width={'size': 2, 'offset': 1}, style={'background-color': 'lightblue'}),

  29.                     dbc.Col('offset=2', width={'size': 2, 'offset': 2}, style={'background-color': 'lightskyblue'}),

  30.                     dbc.Col('3', width=2, style={'background-color': '#e88b00'}),

  31.                     dbc.Col('offset=1', width={'size': 2, 'offset': 1}, style={'background-color': '#8c8c8c'})

  32.                 ],

  33.                 style={'border': '1px solid black'}

  34.             )

  35.         ]

  36.     )

  37. )

  38.  
  39. if __name__ == '__main__':

  40.     app.run_server()

为了更明显,我给每个Row()部件加了轮廓线,可以看到效果非常直观:

 图11

  • 「设置水平对齐方式」

在前面的内容中,我们在同一个Row()部件下组织的所有Col()部件,其顺序都是从左到右一个紧贴下一个排布的,即使设置了offset参数,也只是插空后紧贴。

但在很多页面布局需求中需要对于同一行的多个列元素设置「对齐方式」,这在dash-bootstrap-components中可以通过对Row()部件设置参数justify来实现,可选项有'start''center''end''between'以及'around'五种,每种产生的效果如下面的例子:

app9.py

 
  1. import dash

  2. import dash_bootstrap_components as dbc

  3. import dash_html_components as html

  4.  
  5. app = dash.Dash(

  6.     __name__,

  7.     external_stylesheets=['css/bootstrap.min.css']

  8. )

  9.  
  10. app.layout = html.Div(

  11.     dbc.Container(

  12.         [

  13.             html.Br(),

  14.             html.Br(),

  15.             html.Br(),

  16.             dbc.Row(

  17.                 [

  18.                     dbc.Col('start', width=3, style={'border': '1px solid black'}),

  19.                     dbc.Col('start', width=3, style={'border': '1px solid black'}),

  20.                     dbc.Col('start', width=3, style={'border': '1px solid black'})

  21.                 ],

  22.                 justify='start'

  23.             ),

  24.             html.Br(),

  25.             dbc.Row(

  26.                 [

  27.                     dbc.Col('center', width=3, style={'border': '1px solid black'}),

  28.                     dbc.Col('center', width=3, style={'border': '1px solid black'}),

  29.                     dbc.Col('center', width=3, style={'border': '1px solid black'})

  30.                 ],

  31.                 justify='center'

  32.             ),

  33.             html.Br(),

  34.             dbc.Row(

  35.                 [

  36.                     dbc.Col('end', width=3, style={'border': '1px solid black'}),

  37.                     dbc.Col('end', width=3, style={'border': '1px solid black'}),

  38.                     dbc.Col('end', width=3, style={'border': '1px solid black'})

  39.                 ],

  40.                 justify='end'

  41.             ),

  42.             html.Br(),

  43.             dbc.Row(

  44.                 [

  45.                     dbc.Col('between', width=3, style={'border': '1px solid black'}),

  46.                     dbc.Col('between', width=3, style={'border': '1px solid black'}),

  47.                     dbc.Col('between', width=3, style={'border': '1px solid black'})

  48.                 ],

  49.                 justify='between'

  50.             ),

  51.             html.Br(),

  52.             dbc.Row(

  53.                 [

  54.                     dbc.Col('around', width=3, style={'border': '1px solid black'}),

  55.                     dbc.Col('around', width=3, style={'border': '1px solid black'}),

  56.                     dbc.Col('around', width=3, style={'border': '1px solid black'})

  57.                 ],

  58.                 justify='around'

  59.             )

  60.         ],

  61.         # 为Container两边添加参考线

  62.         style={'border-left': '1px solid red', 'border-right': '1px solid red'}

  63.     )

  64. )

  65.  
  66. if __name__ == '__main__':

  67.     app.run_server()

 图12

2.3 实际案例

通过对上面知识内容的学习,我们掌握了如何基于拓展库dash-bootstrap-components,在Dash中实现bootstrap的网格系统。

下面我们来利用今天学到的知识点,搭建下图所示的登录页面,其中涉及到一些还未给大家介绍的知识点,但很简单,之后的课程会介绍,而涉及到一些额外的css的内容我都已写好注释非常简单~

 图13

对应代码如下:

app10.py

 
  1. import dash

  2. import dash_html_components as html

  3. import dash_bootstrap_components as dbc

  4.  
  5. app = dash.Dash(

  6.     __name__,

  7.     external_stylesheets=['css/bootstrap.min.css']

  8. )

  9.  
  10. app.layout = html.Div(

  11.     [

  12.         html.Br(),

  13.         html.Br(),

  14.         html.Br(),

  15.         html.Br(),

  16.         html.Br(),

  17.         html.Br(),

  18.         html.Br(),

  19.         html.Br(),

  20.         dbc.Container(

  21.             [

  22.                 dbc.Row(style={'height': '30px'}),  # 利用css设置高度

  23.                 dbc.Row(

  24.                     dbc.Col('Email address')

  25.                 ),

  26.                 dbc.Row(

  27.                     dbc.Col(dbc.Input(placeholder='Enter email'))

  28.                 ),

  29.                 dbc.Row(

  30.                     dbc.Col('Password')

  31.                 ),

  32.                 dbc.Row(

  33.                     dbc.Col(dbc.Input(placeholder='Enter Password'))

  34.                 ),

  35.                 dbc.Row(

  36.                     dbc.Col(

  37.                         [

  38.                             'By signing up you accept our ',

  39.                             html.A('Terms Of Use', href='#')

  40.                         ],

  41.                         width={'size': 10, 'offset': 1},

  42.                         style={'text-align': 'center'}  # 利用css设置文字居中

  43.                     ),

  44.                     style={'margin': '6px'}  # 利用css设置上下留白高度

  45.                 ),

  46.                 dbc.Row(

  47.                     dbc.Col(

  48.                         # 利用css实现圆角矩形效果

  49.                         dbc.Button('LOGIN', style={'border-radius': '18px'}, block=True),

  50.                         width={'size': 8, 'offset': 2},

  51.                         style={'text-align': 'center'}

  52.                     )

  53.                 ),

  54.                 dbc.Row(

  55.                     [

  56.                         dbc.Col(html.Hr()),

  57.                         html.P('or', style={'text-align': 'center', 'margin': 0}),

  58.                         dbc.Col(html.Hr())

  59.                     ]

  60.                 ),

  61.                 dbc.Row(

  62.                     dbc.Col(

  63.                         dbc.Button(

  64.                             'Signup using Google',

  65.                             style={'border-radius': '18px'},

  66.                             block=True,

  67.                             outline=True

  68.                         ),

  69.                         width={'size': 8, 'offset': 2},

  70.                         style={'text-align': 'center'}

  71.                     )

  72.                 ),

  73.                 dbc.Row(

  74.                     dbc.Col(

  75.                         [

  76.                             "Don't have account? ",

  77.                             html.A('Sign up here', href='#')

  78.                         ],

  79.                         width={'size': 10, 'offset': 1},

  80.                         style={'text-align': 'center'}

  81.                     ),

  82.                     style={'margin': '6px'}

  83.                 ),

  84.                 html.Br(),

  85.             ],

  86.             style={

  87.                 'background-color': '#ededef',  # 设置背景颜色

  88.                 'max-width': '480px',  # 为Container部件设置最大宽度

  89.                 'border-radius': '12px'

  90.             }

  91.         )

  92.     ]

  93. )

  94.  
  95. if __name__ == '__main__':

  96.     app.run_server()

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
PythonDash是一个用于构建Web应用程序的开源框架。它基于Flask、Plotly.js和React.js等技术,使开发者能够使用Python编写交互式的、具有美观界面的Web应用。 Dash提供了用于构建布局、添加交互式组件和定义回调函数的Python API。开发者可以使用Dash创建各种类型的应用程序,包括数据可视化仪表板、数据分析工具和内部工具等。 Dash的主要特点包括: 1. 简单易用:使用Python编写,无需了解前端开发技术。 2. 交互式可视化:利用Plotly.js库创建交互式图表和可视化组件。 3. 响应式布局:支持自适应布局,在不同设备上都能提供良好的用户体验。 4. 回调函数:通过定义回调函数实现组件之间的交互和数据更新。 5. 扩展性:可以与其他Python库和框架(如Pandas、NumPy、Flask)进行集成。 Dash可以通过安装dash包来使用,例如: ``` pip install dash ``` 然后,你可以在Python代码中导入Dash相关模块并开始构建你的Web应用。例如: ```python import dash import dash_core_components as dcc import dash_html_components as html app = dash.Dash(__name__) app.layout = html.Div( children=[ html.H1("Hello Dash"), dcc.Graph( figure={ "data": [{"x": [1, 2, 3], "y": [4, 1, 2], "type": "bar", "name": "example"}], "layout": {"title": "Dash Bar Chart"}, } ), ] ) if __name__ == "__main__": app.run_server(debug=True) ``` 以上代码创建了一个简单的Dash应用,包含一个标题和一个柱状图。你可以根据自己的需求进一步扩展和定制这个应用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值