【Dash搭建可视化网站】项目6:利用Dash callback高级特性实现货币汇率计算

手动反爬虫,禁止转载:原博地址 https://blog.csdn.net/lys_828/article/details/122088723(CSDN博主:Be_melting)

 知识梳理不易,请尊重劳动成果,文章仅发布在CSDN网站上,在其他网站看到该博文均属于未经作者授权的恶意爬取信息

项目6:利用Dash callback高级特性实现货币汇率计算

之前的项目3,4,5使用的callback都是一对一的数据流向关系,项目6要实现的就是一个输入多个输出的关系,并且尝试进行网页的美化操作。以一个货币汇率计算的小工具为例:用户输入一个值,自动转换出其它三个国家/地区的货币金额。

6.1 基础功能实现

[1] 新建一个py文件,搭建Dash框架,代码如下。xxx中就是待完善的部分。

import dash
from dash import html
from dash import dcc
from dash import dependencies
from dash.dependencies import Output,Input

app = dash.Dash()

app.layout = html.Div(children=[
    xxx
])

app.run_server(debug=True)

[2] 构建输入和输出流向实体。一个输入文本框,三个输出内容。

app.layout = html.Div(children=[
    dcc.Input(value=0,id='ipt'),
    html.Div(['JPY',html.Span('---',id='JPY')]),  
    html.Div(['USD',html.Span('---',id='USD')]),
    html.Div(['GBP',html.Span('---',id='GBP')])
])

[3] 简化代码。对于三个输出的内容,发现存在着大量重复,最直接的反应就是进行函数的封装,代码如下。

def item(name):
    return html.Div([name,html.Span('---',id=name)])
    
app.layout = html.Div(children=[
    dcc.Input(value=0,id='ipt'),
    item('JPY'),
    item('USD'),
    item('GBP')
])

[4] 构建数据输入和输出处理规则。注意是一对三,callback中就是对应的为一个输入三个输出,此外还要留意的就是赋值的参数。即便一个输入,对应的参数赋值是给inputs,但是就是有多个输出,赋值对应的参数也只是output。输入和输出都是放在列表中。

@app.callback(
    output = [Output(),Output(),Output()],
    inputs = [Input()]
)
def rule(rmb):
    return (
        '',
        '',
        ''
    )

接着完善上述代码中要填写的信息,流向实体中输入的id信息和传递的值分别是ipt和value,而对应输出的id信息和传递的值分别是各种货币名称及children(Div中返回的基本就是children),故代码完善如下。

@app.callback(
    output = [Output('JPY','children'),Output('USD','children'),Output('GBP','children')],
    inputs = [Input('ipt','value')]
)
def rule(rmb):
    return (
        f'{rmb*15.0}',
        f'{rmb*0.14}',
        f'{rmb*0.11}'
    )

直接保存后运行,刷新网址:http://127.0.0.1:8050/,输出结果如下。提示最后传递的数据没有办法进行相乘,需要对输出的数据类型进行判别后转化为数值,再进行操作。
请添加图片描述
[5] Bug调试。可以在return前面的一行加上print(type(rmb))语句,然后再次保存程序后运行,刷新网址:http://127.0.0.1:8050/,输出结果如下。
请添加图片描述
注意左侧的输出结果,首先网址打开后返回的是默认值0,数据类型为int整型,然后按退格键把0删除后,就是空值,这里按照是字符串数据类型,然后再输入12,两个数值都被当做了str字符串。可以在这里进行数据类型的判断以及空值的处理,但是有简单的方式就是在构建输入框的时候设定数据类型为数值型,进一步处理空值。

dcc.Input(value=0,id='ipt',type='number')
def rule(rmb):
    rmb = rmb if rmb is not None else 0
    return (
        f'{rmb*15.0}',
        f'{rmb*0.14}',
        f'{rmb*0.11}'
    )

修改完毕保存后运行,刷新网址:http://127.0.0.1:8050/,输出结果如下。解决了bug,而且输入框中由于限定了数值类型,其它字母什么都没有办法输入,相当于增加了容错,最后也可以正常的实现货币汇率的计算。
请添加图片描述
可以打开网页下方的调试按钮,查看一下callback的情况,对应的输入和输出就和设计的一模一样。
请添加图片描述

6.2 利用bootstrap组件美化货币汇率计算工具

前面的内容已经实现了基本的货币转化的逻辑输出,剩下的内容就是对内容进行美化处理。这部分两个核心知识点:(1)如何安装/加载Dash bootstrap components, (2)组件的使用技巧。

[1] 安装Dash bootstrap components。打开命令行执行安装语句:pip install dash-bootstrap-components。官网所在地址:http://dash-bootstrap-components.opensource.faculty.ai/。
请添加图片描述
关于bootstrap,其实就是在web开发届相当老牌的一个框架,官网网址:https://getbootstrap.com/docs/4.6/getting-started/introduction/。利用里面已经成熟的框架可以快速的搭建网站。而dash-bootstrap-components模块基本上把bootstrap里面的80%的components组件都给封装进去,直接使用python的语法就能实现网站的搭建。

[2] 加载bootstrap中的css样式。首先将css样式引入到当前的项目环境中,可以采用官方给的示例,使用代码的方式进行操作。

import dash_bootstrap_components as dbc
app = dash.Dash(
    external_stylesheets=[dbc.themes.BOOTSTRAP]
)

其实更好的方式:就是把对应的网址的bootstrap.min.css直接下载到项目中的assets文件夹下,就可以实现自动加载。css样式可选网址:https://cdnjs.com/。比如选择twitter-bootstrap的css样式。
请添加图片描述
搜索结果第一个点击进去后,跳转页面,复制红框中的样式。
请添加图片描述
打开浏览器在地址栏中粘贴刚刚的内容,回车后在页面中鼠标右键,选择另存为到assets文件夹中即可。
请添加图片描述
[3] 创建组件。打开dash-bootstrap-components官网所在地址:http://dash-bootstrap-components.opensource.faculty.ai/。找到想要创建的类型组件,比如这里把三种货币的输出结果以listgroup的形式展示出来,官方给的示例代码如下。
请添加图片描述
按照提示,在py文件中添加相应的代码,然后把list_group添加到app.layout中,代码如下。

import dash
from dash import html
from dash import dcc
from dash.dependencies import Input,Output
import dash_bootstrap_components as dbc

app = dash.Dash()

list_group = dbc.ListGroup(
    [
        dbc.ListGroupItem("Item 1"),
        dbc.ListGroupItem("Item 2"),
        dbc.ListGroupItem("Item 3"),
    ]
) 

app.layout = html.Div([list_group])

@app.callback(
    output = [Output('JPY','children'),Output('USD','children'),Output('GBP','children')],
    inputs = [Input('ipt','value')]
)
def rule(rmb):
    rmb = rmb if rmb is not None else 0
    return (
        f'{rmb*15.0}',
        f'{rmb*0.14}',
        f'{rmb*0.11}'
    )

app.run_server(debug=True)

修改完毕保存后运行,刷新网址:http://127.0.0.1:8050/,输出结果如下。实现了内容的添加,但是没有和要表达的信息进行联动,也就是没有指定id信息,所以报了4个错都是id not found。
请添加图片描述
[4] 修改默认组件中的内容。把input和output中的数据添加到组件中,形成完整的信息流。具体的内容就是一个输入三个输出。模仿6.1中步骤[2]和[3]中的代码,先尝试进行内容的输入输出,搭建好框架。

app.layout = html.Div(children=[
    dbc.ListGroup([
        dbc.Input(value=0,id='ipt',type='number'),
        dbc.ListGroupItem(['JPY: ',html.Span('--',id='JPY')]),
        dbc.ListGroupItem(['USD: ',html.Span('--',id='USD')]),
        dbc.ListGroupItem(['GBP: ',html.Span('--',id='GBP')]),
    ])
])

修改完毕保存后运行,刷新网址:http://127.0.0.1:8050/,输出结果如下。可以基本上实现要求,接下来就可以进行页面美化的操作以及代码简化。
请添加图片描述
[5] 代码简化与页面美化设计。先对重复的代码进行函数的封装,为了更清晰地展示前面三个字符代表的含义,可以添加对应的图像辅助理解,顺便巩固之前项目1中图片添加的知识点。

def item(name,img_path):
    return dbc.ListGroupItem([
        name,
        html.Img(src=img_path),
        html.Span('--',id=name)
    ])

app.layout = html.Div(children=[
    dbc.ListGroup([
        dbc.Input(value=0,id='ipt',type='number'),
        item('JPY','./assets/jp.png'),
        item('USD','./assets/usa.png'),
        item('GBP','./assets/uk.png'),
    ])
])

def rule(rmb):
    rmb = rmb if rmb is not None else 0
    return (
        f'{rmb*15.0} ¥',
        f'{rmb*0.14} $',
        f'{rmb*0.11} £',
    )

修改完毕保存后运行,刷新网址:http://127.0.0.1:8050/,输出结果如下。要显示的信息都显示出来了,接下来就是调整一下位置。
请添加图片描述
比如将国旗调整到对应货币简称字母的下面,换算的金额和对应的符号调整到右边。如果不指定标签直接给出添加的数据信息,比如这里的name,就是直接和下面的图片属于同一行,当指定了H5标签后就实现了自动换行。此外对应数据布置的问题,可以使用className进行设置,float本意就是飘、浮动的意思,所以float-right就是相当于是右对齐的感觉。

def item(name,img_path):
    return dbc.ListGroupItem([
        html.H5(name),
        html.Img(src=img_path),
        html.H5('--',id=name,className='float-right')
    ])

修改完毕保存后运行,刷新网址:http://127.0.0.1:8050/,输出结果如下。
请添加图片描述
[6] 头部信息的显示。还是参考官方的代码及输出样式,只需要添加一个active参数既可以完成。

app.layout = html.Div(children=[
    dbc.ListGroup([
        dbc.ListGroupItem(children=[
            html.H1("汇率计算器-简单版"),
            html.P('write something here'),
            dbc.Input(value=0,id='ipt',type='number'),
        ],active=True),
        item('JPY','./assets/jp.png'),
        item('USD','./assets/usa.png'),
        item('GBP','./assets/uk.png'),
    ])
])

但是这里面仍有需要留意的地方,将dbc.Input组件包装在dbc.ListGroupItem下面,里面是可以再添加html中的信息内容,比如这里的H1和P标签对应的信息。还有就是官网中给出的children只是单个的字符串数据,这里实际上可以添加多个元素,用列表传递。
请添加图片描述
修改完毕保存后运行,刷新网址:http://127.0.0.1:8050/,输出结果如下。
请添加图片描述
[7] 解决居中问题。只需要将原来的布局由html.Div修改为dbc.Container即可,由于默认是水平居中,所以对于组件的上方距离需要人为手动的进行调整,这个参数就是stlye中的padding,需要注意style不要添加位置错误。

app.layout = dbc.Container(children=[
    dbc.ListGroup([
        dbc.ListGroupItem(children=[
            html.H1("汇率计算器-简单版"),
            html.P('write something here'),
            dbc.Input(value=0,id='ipt',type='number'),
        ],active=True),
        item('JPY','./assets/jp.png'),
        item('USD','./assets/usa.png'),
        item('GBP','./assets/uk.png'),
    ],style={'padding':'3rem'})
])

修改完毕保存后运行,刷新网址:http://127.0.0.1:8050/,输出结果如下。
请添加图片描述
[8] 简单的UI设计,比如添加一个阴影效果。这种设计需要在官网中的Utilities中查找。除此之外还有很多可以自定义的小设计都可以在Utilities下进行查找。官网地址:https://getbootstrap.com/docs/4.6/utilities/shadows/。
请添加图片描述
具体在代码中的操作如下。就是对整个dbc.ListGroup进行属性的添加,注意添加的位置。

app.layout = dbc.Container(children=[
    dbc.ListGroup([
        dbc.ListGroupItem(children=[
            html.H1("汇率计算器-简单版"),
            html.P('write something here'),
            dbc.Input(value=0,id='ipt',type='number'),
        ],active=True),
        item('JPY','./assets/jp.png'),
        item('USD','./assets/usa.png'),
        item('GBP','./assets/uk.png'),
    ],style={'padding':'3rem'},className='shadow')  #只修改了这里
])

修改完毕保存后运行,刷新网址:http://127.0.0.1:8050/,输出结果如下。
请添加图片描述
仔细一点可以发现这里的阴影貌似并不是我们想要的效果,应该加在里面的内容部分,错误就出在了style的样式的添加,这里的style加在了dbc.ListGroup中,表示相对于dbc.Container来说的一个padding距离,而实际上应该是dbc.Container相对于整个html的padding距离,调整一下style的位置后代码如下。

app.layout = dbc.Container(children=[
    dbc.ListGroup([
        dbc.ListGroupItem(children=[
            html.H1("汇率计算器-简单版"),
            html.P('write something here'),
            dbc.Input(value=0,id='ipt',type='number'),
        ],active=True),
        item('JPY','./assets/jp.png'),
        item('USD','./assets/usa.png'),
        item('GBP','./assets/uk.png'),
    ],className='shadow')
],style={'padding':'3rem'})  #style添加在dbc.Container中

修改完毕保存后运行,刷新网址:http://127.0.0.1:8050/,输出结果如下。很完美达到目的效果。
请添加图片描述
至此整个项目6,利用Dash callback高级特性实现货币汇率计算全部过程就介绍完毕。核心知识点包含:callback一个输出对应多个输出的设计,Dash bootstrap components组件的使用,以及如何利用bootstrap实现页面的美化。

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
好的,利用Dash和Plotly库实现仓库最短拣货路径可视化看板的过程分为以下几步: 1. 准备数据:你需要创建一个包含储位坐标和路径的数据集,并将其存储为CSV文件。例如,你可以创建一个名为“warehouse.csv”的文件,其内容如下所示: ``` x,y,location,path 0,0,A, 1,2,B,A-C-D-E 3,1,C,A-B-D-E 5,4,D,A-B-C-E 2,3,E,A-B-C-D ``` 注意,这个数据集包含每个储位的坐标(x和y),储位编号(location)和路径(path)。路径中使用“-”分隔储位编号,表示从一个储位到另一个储位的路径。 2. 创建Dash应用程序:你需要创建一个Dash应用程序来加载数据集并绘制仓库地图和最短拣货路径。以下是一个简Dash应用程序示例: ``` import dash import dash_core_components as dcc import dash_html_components as html import pandas as pd import plotly.graph_objs as go # 加载数据集 df = pd.read_csv('warehouse.csv') # 创建Dash应用程序 app = dash.Dash(__name__) # 定义样式 colors = { 'background': '#111111', 'text': '#7FDBFF' } # 创建布局 app.layout = html.Div(style={'backgroundColor': colors['background']}, children=[ html.H1(children='Warehouse Map', style={ 'textAlign': 'center', 'color': colors['text'] }), dcc.Graph( id='warehouse-map', figure={ 'data': [ go.Scatter(x=df['x'], y=df['y'], mode='markers', text=df['location'], name='Locations'), ], 'layout': go.Layout( xaxis={'title': 'X'}, yaxis={'title': 'Y'}, margin={'l': 40, 'b': 40, 't': 10, 'r': 10}, legend={'x': 0, 'y': 1}, hovermode='closest' ) } ), html.H1(children='Shortest Path', style={ 'textAlign': 'center', 'color': colors['text'] }), dcc.Graph( id='shortest-path', figure={ 'data': [ go.Scatter(x=df['x'], y=df['y'], mode='markers', text=df['location'], name='Locations'), go.Scatter(x=[], y=[], mode='lines', name='Path'), ], 'layout': go.Layout( xaxis={'title': 'X'}, yaxis={'title': 'Y'}, margin={'l': 40, 'b': 40, 't': 10, 'r': 10}, legend={'x': 0, 'y': 1}, hovermode='closest' ) } ), ]) # 回调函数:响应用户选择路径事件 @app.callback( dash.dependencies.Output('shortest-path', 'figure'), [dash.dependencies.Input('warehouse-map', 'clickData')]) def update_shortest_path(clickData): if clickData is None: return {'data': []} else: location = clickData['points'][0]['text'] path = df[df['location'] == location].iloc[0]['path'] locations = path.split('-') x = [df[df['location'] == l].iloc[0]['x'] for l in locations] y = [df[df['location'] == l].iloc[0]['y'] for l in locations] return { 'data': [ go.Scatter(x=df['x'], y=df['y'], mode='markers', text=df['location'], name='Locations'), go.Scatter(x=x, y=y, mode='lines', name='Path'), ], 'layout': go.Layout( xaxis={'title': 'X'}, yaxis={'title': 'Y'}, margin={'l': 40, 'b': 40, 't': 10, 'r': 10}, legend={'x': 0, 'y': 1}, hovermode='closest' ) } if __name__ == '__main__': app.run_server(debug=True) ``` 这个应用程序将加载“warehouse.csv”文件,并使用Dash框架创建一个Web应用程序。它将创建一个仓库地图,其中每个储位都用一个点表示,并将创建一个最短拣货路径图,其中用户可以击储位来选择路径。 3. 运行应用程序:在终端中运行上面的代码(确保安装了Dash和Plotly库),然后在Web浏览器中打开http://127.0.0.1:8050/。你将看到一个仓库地图和一个空的最短拣货路径图。击地图上的任何一个点,最短拣货路径将被绘制出来。 如此,你就实现了仓库最短拣货路径可视化看板。当然,你可以根据需要对代码进行修改和定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lys_828

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值