博客
关于我
(数据科学学习手札119)Python+Dash快速web应用开发——多页面应用
阅读量:424 次
发布时间:2019-03-06

本文共 6191 字,大约阅读时间需要 20 分钟。

Python + Dash 快速开发多页面Web应用

项目简介

本文是“Python + Dash 快速开发多页面Web应用”教程系列的第16篇。在前面的教程中,我们通过搭建单页面的Dash应用,掌握了如何快速开发功能丰富的Web应用。然而随着应用的功能日趋完善,单页面的内容组织方式逐渐无法满足复杂的需求,也不利于构建逻辑清晰的Web应用。

因此,我们需要在Dash应用中引入路由功能。通过在主域名下根据不同的URL渲染不同内容,就像大多数现代网站一样实现多页面应用。

本文将教你如何在Dash中编写多页面应用并进行路由控制。

Dash 应用路由基础

2.1 Location 组件的基础使用

要在Dash中实现URL路由,首先需要捕获浏览器地址栏中的URL信息。Dash中可以通过构建可以持续监听当前应用URL信息的组件来实现。

我们使用dash_core_components中的Location()组件。其核心属性包括hrefpathnamesearchhash,可以记录地址栏中的相应信息。

以下示例展示了如何通过Location()组件捕获不同URL参数:

app1.py
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.layout = dcc.Container([
dcc.Location(id='url'),
html.Ul(id='output-url')
], style={'paddingTop': '100px'})
@app.callback(
Output('output-url', 'children'),
[Input('url', 'href'),
Input('url', 'pathname'),
Input('url', 'search'),
Input('url', 'hash')])
def show_location(href, pathname, search, hash):
return [
html.Li(f'当前href为:{href}'),
html.Li(f'当前pathname为:{pathname}'),
html.Li(f'当前search为:{search}'),
html.Li(f'当前hash为:{hash}')
]
if __name__ == '__main__':
app.run_server(debug=True)

2.2 利用 Location 实现页面重定向

除了捕获URL信息,Location()组件还可以用于实现页面重定向。通过将Location()作为回调函数的输出(记得设置id属性),地址栏URL会在回调完成后跳转。

以下示例展示了如何通过Location()实现重定向:

app3.py
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.layout = html.Div([
html.Div(id='redirect-url-container'),
dbc.Button('跳转到页面A', id='jump-to-pageA', style={'marginRight': '10px'}),
dbc.Button('跳转到页面B', id='jump-to-pageB'),
], style={'paddingTop': '100px'})
@app.callback(
Output('redirect-url-container', 'children'),
[Input('jump-to-pageA', 'n_clicks'),
Input('jump-to-pageB', 'n_clicks')])
def jump_to_target(a_n_clicks, b_n_clicks):
ctx = dash.callback_context
if ctx.triggered[0]['prop_id'] == 'jump-to-pageA.n_clicks':
return dcc.Location(id='redirect-url', href='/pageA')
elif ctx.triggered[0]['prop_id'] == 'jump-to-pageB.n_clicks':
return dcc.Location(id='redirect-url', href='/pageB')
return dash.no_update
if __name__ == '__main__':
app.run_server(debug=True)

除了Location()组件,dash_core_components中的Link()组件提供了更好的替代方案。Link()组件的refresh参数默认为False,实现了无缝页面切换。

以下示例展示了如何使用Link()组件实现无缝切换:

app4.py
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.layout = dbc.Container([
dcc.Location(id='url'),
dcc.Link('页面A', href='/pageA', refresh=True),
html.Br(),
dcc.Link('页面B', href='/pageB'),
html.Hr(),
html.H1(id='render-page-content')
], style={'paddingTop': '100px'})
@app.callback(
Output('render-page-content', 'children'),
Input('url', 'pathname'))
def render_page_content(pathname):
if pathname == '/':
return '欢迎来到首页'
elif pathname == '/pageA':
return '欢迎来到页面A'
elif pathname == '/pageB':
return '欢迎来到页面B'
elif pathname == '/pageC':
return '欢迎来到页面C'
else:
return '当前页面不存在!'
if __name__ == '__main__':
app.run_server(debug=True)

动手开发个人博客网站

掌握以上知识后,我们来用Dash开发一个简单的个人博客网站。思路是在Location监听URL变化的前提下,后台利用网络爬虫从博客园Dash主题下爬取相应网页内容,并根据用户访问渲染对应文章。

以下是一个实现示例:

app5.py
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
import dash_dangerously_set_inner_html
from dash.dependencies import Input, Output
import re
import requests
from lxml import etree
app = dash.Dash(__name__, suppress_callback_exceptions=True)
app.layout = html.Div(
dbc.Spinner(
dbc.Container([
dcc.Location(id='url'),
html.Div(id='page-content')
], style={
'paddingTop': '30px',
'paddingBottom': '50px',
'borderRadius': '10px',
'boxShadow': 'rgb(0 0 0 / 20%) 0px 13px 30px, rgb(255 255 255 / 80%) 0px -13px 30px'
}),
fullscreen=True
))
)
@app.callback(
Output('article-links', 'children'),
Input('url', 'pathname'))
def render_article_links(pathname):
response = requests.get('https://www.cnblogs.com/feffery/tag/Dash/',
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'
})
tree = etree.HTML(response.text)
posts = [
(href, title.strip())
for href, title in zip(
tree.xpath("//div[@class='postTitl2']/a/@href"),
tree.xpath("//div[@class='postTitl2']/a/span/text()")
)
]
return [
html.Li(
dcc.Link(title, href=f'/article-{href.split("/")[-1]}', target='_blank')
) for href, title in posts
]
@app.callback(
Output('page-content', 'children'),
Input('url', 'pathname'))
def render_article_content(pathname):
if pathname == '/':
return [
html.H2('博客列表:'),
html.Div(
id='article-links',
style={'width': '100%'}
)
]
elif pathname.startswith('/article-'):
response = requests.get(
f'https://www.cnblogs.com/feffery/p/{re.findall("\d+", pathname)[0]}.html',
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'
}
)
tree = etree.HTML(response.text)
return [
html.H3(tree.xpath("//title/text()")[0].split(' - ')[0]),
html.Em('作者:费弗里'),
dash_dangerously_set_inner_html.DangerouslySetInnerHTML(
unescape(etree.tostring(
tree.xpath('//div[@id="cnblogs_post_body"]')[0],
method='text'
).decode())
)
]
return dash.no_update
if __name__ == '__main__':
app.run_server(debug=True)

按照类似的方法,你可以根据需求开发自己的多页面应用,并进一步丰富功能。

你可能感兴趣的文章
OpenMCU(四):STM32F103启动汇编代码分析
查看>>
OpenMetadata 命令执行漏洞复现(CVE-2024-28255)
查看>>
OpenMMLab | AI玩家已上线!和InternLM解锁“谁是卧底”新玩法
查看>>
OpenMMLab | S4模型详解:应对长序列建模的有效方法
查看>>
OpenMMLab | 【全网首发】Llama 3 微调项目实践与教程(XTuner 版)
查看>>
OpenMMLab | 不是吧?这么好用的开源标注工具,竟然还有人不知道…
查看>>
OpenMMLab | 如何解决大模型长距离依赖问题?HiPPO 技术深度解析
查看>>
OpenMMLab | 面向多样应用需求,书生·浦语2.5开源超轻量、高性能多种参数版本
查看>>
OpenMP 线程互斥锁
查看>>
OpenMV入门教程(非常详细)从零基础入门到精通,看完这一篇就够了
查看>>
OpenObserve云原生可观测平台本地Docker部署与远程访问实战教程
查看>>
openoffice使用总结001---版本匹配问题unknown document format for file: E:\apache-tomcat-8.5.23\webapps\ZcnsDms\
查看>>
views
查看>>
OpenPPL PPQ量化(2):离线静态量化 源码剖析
查看>>
OpenPPL PPQ量化(3):量化计算图的加载和预处理 源码剖析
查看>>
OpenPPL PPQ量化(4):计算图的切分和调度 源码剖析
查看>>
OpenPPL PPQ量化(5):执行引擎 源码剖析
查看>>
openpyxl 模块的使用
查看>>
OpenResty & Nginx:详细对比与部署指南
查看>>
openresty 前端开发入门六之调试篇
查看>>