ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【Python百日基础系列】Day26 - Dash回调初识和组件

2021-11-14 12:34:49  阅读:484  来源: 互联网

标签:__ dash Python app Day26 Dash html 组件 import


文章目录

视频讲解:

一、什么是Dash回调?

1.1 回调的作用

Dash应用程序通过Dash回调函数实现交互:当输入组件的属性发生变化时,自动调用编写好的Python函数。可以把多个回调函数链接起来,即UI输入组件中的一个变动,触发整个应用程序中的几个变动。

1.2 回调的实现

Dash通过装饰器函数来实现回调:应用程序接口Input和Ouput是通过app.callback装饰器声明的

二、带回调功能的组件

2.1 按钮

import dash
from dash import dcc
from dash import html

# css样式表无法下载,返回403错误
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[
    html.Div(dcc.Input(id='input-box', type='text')),
    html.Button('提交', id='button'),
    html.Div(id='output-container-button',
             children='输入完毕,请点击提交按钮。')
])


@app.callback(
    dash.dependencies.Output('output-container-button', 'children'),
    [dash.dependencies.Input('button', 'n_clicks')],
    [dash.dependencies.State('input-box', 'value')])
def update_html(n_clicks, values):
    print(values, type(values))     # 你好吗 <class 'str'>
    print(n_clicks, type(n_clicks)) # 1 <class 'int'>
    return f'输入内容:"{values}" ,提交了 {n_clicks} 次'


if __name__ == '__main__':
    app.run_server(debug=True)

在这里插入图片描述

2.2 上传组件1:解析 CSV 或 Excel 文件并将结果显示在表格中

import base64
import datetime
import io

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

import pandas as pd

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    dcc.Upload(
        id='upload-data',
        children=html.Div([
            '请将Excel或CSV文件拖放到此处,或 ',
            html.A('选择文件')
        ]),
        style={
            'width': '100%',        # 宽度
            'height': '60px',       # 高度
            'lineHeight': '60px',   # 线高
            'borderWidth': '1px',   # 边框宽度
            'borderStyle': 'dashed', # 边框样式
            'borderRadius': '5px',  # 边框半径
            'textAlign': 'center',  # 文字居中
            'margin': '10px'        # 外边距
        },
        # 允许同时上传多个文件
        multiple=True
    ),
    html.Div(id='output-data-upload'),
])

def parse_contents(contents, filename, date):
    content_type, content_string = contents.split(',')

    decoded = base64.b64decode(content_string)
    try:
        if 'csv' in filename:
            # 上传了一个CSV文件
            df = pd.read_csv(
                io.StringIO(decoded.decode('utf-8')))
        elif 'xls' in filename:
            # 上传了一个Excel文件
            df = pd.read_excel(io.BytesIO(decoded))
    except Exception as e:
        print(e)
        return html.Div([
            'Sorry,处理文件出错。'
        ])

    return html.Div([
        html.H5(filename),
        # 从时间戳转化为日期时间字符串
        html.H6(datetime.datetime.fromtimestamp(date)),

        dash_table.DataTable(
            data=df.to_dict('records'),
            columns=[{'name': i, 'id': i} for i in df.columns]
        ),

        html.Hr(),  # 分割线

        # 为了测试,通过浏览器显示原始数据
        html.Div('原始数据'),
        html.Pre(contents[0:200] + '...', style={
            'whiteSpace': 'pre-wrap',
            'wordBreak': 'break-all'
        }),
        html.Pre(str(df.to_dict('records'))),
    ])

@app.callback(Output('output-data-upload', 'children'),
              Input('upload-data', 'contents'),
              State('upload-data', 'filename'),
              State('upload-data', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
    """ 装饰器 Input  State  State 中的值分别传给本函数的三个参数 """
    if list_of_contents is not None:
        children = [
            parse_contents(c, n, d) for c, n, d in
            zip(list_of_contents, list_of_names, list_of_dates)]
        return children

if __name__ == '__main__':
    app.run_server(debug=True)

在这里插入图片描述

2.3 上传组件2:上传图像并在页面显示

import datetime

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

# css无法访问,无效
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    dcc.Upload(
        id='upload-image',
        children=html.Div([
            '拖放图像文件到此,或 ',
            html.A('选择文件。')
        ]),
        style={
            'width': '100%',
            'height': '60px',
            'lineHeight': '60px',
            'borderWidth': '1px',
            'borderStyle': 'dashed',
            'borderRadius': '5px',
            'textAlign': 'center',
            'margin': '10px'
        },
        # 允许同时上传多个文件
        multiple=True
    ),
    html.Div(id='output-image-upload'),
])

def parse_contents(contents, filename, date):
    return html.Div([
        html.H5(filename),
        html.H6(datetime.datetime.fromtimestamp(date)),
        # 在 Dash 上传模块的支持下,html.IMG可以直接显示图像文件
        html.Img(src=contents, width=600),
        html.Hr(),
    ])

@app.callback(Output('output-image-upload', 'children'),
              Input('upload-image', 'contents'),
              State('upload-image', 'filename'),
              State('upload-image', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
    if list_of_contents is not None:
        children = [
            parse_contents(c, n, d) for c, n, d in
            zip(list_of_contents, list_of_names, list_of_dates)]
        return children

if __name__ == '__main__':
    app.run_server(debug=True)

在这里插入图片描述

2.4 上传组件的三种使用方式

import dash
from dash import dcc
from dash import html

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
    dcc.Upload(html.Button('上传文件')),
    html.Hr(),
    dcc.Upload(html.A('上传文件')),
    html.Hr(),
    dcc.Upload([
        '拖放文件到此,或 ',
        html.A('选择一个文件')
    ], style={
        'width': '100%',
        'height': '60px',
        'lineHeight': '60px',
        'borderWidth': '1px',
        'borderStyle': 'dashed',
        'borderRadius': '5px',
        'textAlign': 'center'
    })
])

if __name__ == '__main__':
    app.run_server(debug=True)

在这里插入图片描述

2.5 上传属性:help(dash.dcc.Upload)

children(列表或单个破折号组件,字符串或数字 | 字符串;可选):上传组件的内容。
id( string ; 可选): 该组件的 ID,用于标识回调中的 dash 组件。ID 需要在应用程序中的所有组件中都是唯一的。
accept(字符串;可选):允许特定类型的文件。有关更多信息,请参阅 https://github.com/okonet/attr-accept。

  • 请记住,mime 类型确定在跨平台上并不可靠。例如,CSV 文件在 macOS 下报告为 text/plain,但在 Windows 下报告为 application/vnd.ms-excel。在某些情况下,可能根本没有设置 MIME 类型。请参阅:https : //github.com/react-dropzone/react-dropzone/issues/276。
    className(字符串;可选):组件的 HTML 类名。
    className_active(字符串;可选):活动时组件的 HTML 类名。
    className_disabled(字符串;可选):组件的 HTML 类名称(如果禁用)。
    className_reject(字符串;可选):如果被拒绝,组件的 HTML 类名。
    contents(字符串 | 字符串列表;可选):上传文件的内容作为二进制字符串。
    disable_click( boolean ; default False): 不允许点击组件打开文件对话框。
    disabled( boolean ; default False): 完全启用/禁用上传组件。
    filename(字符串 | 字符串列表;可选):上传的文件的名称。请注意,这不包括文件的路径(出于安全原因)。
    last_modified( number | list of numbers ; optional): 上传文件的最后修改日期在unix时间(自1970年以来的秒数)。
    loading_state( dict ; 可选): 保存来自 dash-renderer 的加载状态对象的对象。
    loading_state 是一个带键的字典:
  • component_name(字符串;可选):保存正在加载的组件的名称。
  • is_loading(boolean ; 可选):确定组件是否正在加载。
  • prop_name(字符串;可选):保存正在加载的属性。
    max_size(数字;默认-1):最大文件大小(以字节为单位)。如果-1,则无穷大。
    min_size(数字;默认0):最小文件大小(以字节为单位)。
    multiple( boolean ; default False): 允许删除多个文件。
    style(dict ; 可选):要应用的 CSS 样式。
    style_active( dict ; default { borderStyle: ‘solid’, borderColor: ‘#6c6’, backgroundColor: ‘#eee’,}):活动时应用的 CSS 样式。
    style_disabled( dict ; default { opacity: 0.5,}): CSS 样式(如果禁用)。
    style_reject( dict ; default { borderStyle: ‘solid’, borderColor: ‘#c66’, backgroundColor: ‘#eee’,}): CSS 样式,如果被拒绝。

2.6 下载组件:下载文本

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

app = dash.Dash(prevent_initial_callbacks=True)

app.layout = html.Div(children=
    [html.Button("下载文本", id="btn_txt"),
     dcc.Download(id="download-text-index")]
)


@app.callback(
    Output("download-text-index", "data"),
    Input("btn_txt", "n_clicks"))
def func(n_clicks):
    if n_clicks is None:
        raise dash.exceptions.PreventUpdate
    else:
        return dict(content="这是将要保存的文本内容。", filename="hello.txt")


if __name__ == "__main__":
    app.run_server(debug=True)

在这里插入图片描述

2.7 下载组件:DataFrame下载为CSV

import dash
from dash.dependencies import Output, Input
from dash import html
from dash import dcc
import pandas as pd

app = dash.Dash(__name__)
app.layout = html.Div(
    [
        html.Button("下载CSV", id="btn_csv"),
        # 下载组件
        dcc.Download(id="download-dataframe-csv"),
    ]
)

df = pd.DataFrame({"a": [1, 2, 3, 4],
                   "b": [2, 1, 5, 6],
                   "c": ["x", "x", "y", "y"]})


@app.callback(
    Output("download-dataframe-csv", "data"),
    Input("btn_csv", "n_clicks"),
    prevent_initial_call=True,
)
def func(n_clicks):
    return dcc.send_data_frame(df.to_csv, "mydf.csv")


if __name__ == "__main__":
    app.run_server(debug=True)

在这里插入图片描述

2.8 下载组件:DataFrame下载为Excel

import dash
from dash.dependencies import Output, Input
from dash import html
from dash import dcc
import pandas as pd

app = dash.Dash(__name__)
app.layout = html.Div(
    [
        html.Button("下载为Excel文件", id="btn_xlsx"),
        # 下载组件
        dcc.Download(id="download-dataframe-xlsx"),
    ]
)

df = pd.DataFrame({"a": [1, 2, 3, 4],
                   "b": [2, 1, 5, 6],
                   "c": ["x", "x", "y", "y"]})


@app.callback(
    Output("download-dataframe-xlsx", "data"),
    Input("btn_xlsx", "n_clicks"),
    prevent_initial_call=True,		# 阻止首次回调
)
def func(n_clicks):
    return dcc.send_data_frame(df.to_excel, "mydf.xlsx", sheet_name="Sheet_name_1")


if __name__ == "__main__":
    app.run_server(debug=True)

在这里插入图片描述

2.9 下载组件:下载图像

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

app = dash.Dash(__name__)
app.layout = html.Div([
    html.Button("下载图像", id="btn_image"),
    dcc.Download(id="download-image")
])


@app.callback(
    Output("download-image", "data"),
    Input("btn_image", "n_clicks"),
    prevent_initial_call=True,  # 阻止首次回调
)
def func(n_clicks):
    return dcc.send_file("QR-PyDataLab.jpg")


if __name__ == "__main__":
    app.run_server(debug=True)

在这里插入图片描述

2.10 下载属性

help(dash.dcc.Download)

id( string ; 可选): 该组件的 ID,用于标识回调中的 dash 组件。
base64( boolean ; default False):base64 的默认值,在未设置为数据属性的一部分时使用。
data(dict ; 可选):更改时,调用下载。
data 是一个带键的字典:

  • base64(布尔值;可选):设置为 True,当数据采用 base64 编码时。
  • content(字符串;必需):文件内容。
  • filename( string ; required): 下载对话框中建议的文件名。
  • type(字符串;可选):Blob 类型,通常是 MIME 类型。
    type( string ; default ‘text/plain’): type 的默认值,在未设置为 data 属性的一部分时使用。

标签:__,dash,Python,app,Day26,Dash,html,组件,import
来源: https://blog.csdn.net/yuetaope/article/details/121313545

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有