[PYTHON] Supprimez les composants et les rappels de app.py avec plotly Dash

Chose que tu veux faire

--Créez une page Web de taille raisonnable avec un tiret ―― Tout écrire dans app.py n'est pas facile à maintenir, je veux donc le diviser

Comme d'habitude, je ne trouve aucun document en anglais, je vais donc les écrire ensemble.

splitting callback and components in multiple files use the : deepl

À propos, l'échantillon officiel lui-même existe en grand nombre, mais il y a toujours des centaines de lignes de app.py.

Cela fait environ 2 mois que j'ai touché au tableau de bord, alors faites-moi savoir s'il existe une meilleure solution.

Ce que j'ai fait

Pensez à la structure du fichier

Première histoire ↓

.
├── app.py
├── assets
│   ├── common.css
│   └── default.css
└── src
    └── some_utils.py

↓ Il semble que cela devrait être fait

.
├── app.py
├── assets
│   ├── common.css
│   └── default.css
│
└── src
    ├── callback.py
    ├── callbacks
    │   ├── hoge.py
    │   ├── fuga.py
    │   └── poyo.py
    │
    ├── layout.py
    ├── components
    │   ├── fizz.py
    │   ├── buzz.py
    │   ├── boo.py
    │   └── bar.py
    │
    ├── some_utils.py
    └── utils

Organisez app.py

J'emprunte la source de mon autre article car c'est un gros problème

Implémentation d'un bouton pour sélectionner / décocher tous les états de contrôle de dcc.CheckList dans Dash

python app.py

Commencez par et pouvez naviguer sur http: // localhost: 8050

↓ Cela devient un tel écran スクリーンショット 2020-02-19 15.43.06.png

app.py


import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table
from dash.dependencies import Input, Output, State
from flask import Flask, request

import time

server = Flask(__name__)
app = dash.Dash(__name__, server=server)

app.title = 'checklist-test'

selected_key = None


checklists = dcc.Checklist(
    id='checklist-states',
    options=[
        {'label': 'New York City', 'value': 'NYC'},
        {'label': 'Montréal', 'value': 'MTL'},
        {'label': 'San Francisco', 'value': 'SF'}
    ],
    value=['MTL', 'SF']
)


app.layout = html.Div(id='main',children=[
    html.H1(children='Test de la liste de contrôle'),
    dcc.Location(id='location', refresh=False),
    html.Div(className='main-block', children=[checklists]),
    html.Div(className='second', children=[
        html.Button('Tout sélectionner', id='filter-check-button', className='filter_button'),
        html.Button('Tout annuler', id='filter-remove-button', className='filter_button')
        ])
    ])


@app.callback(
    [Output('checklist-states', 'value')],
    [Input('filter-check-button', 'n_clicks_timestamp'),
    Input('filter-remove-button', 'n_clicks_timestamp')],
    [State('checklist-states', 'value')]
)
def update_check(all_check, all_remove, checking):

        if not all_check is None:
            if (time.time() * 1000 - all_check) < 1000:
                return [['NYC', 'MTL', 'SF']]

        if not all_remove is None:
            if (time.time() * 1000 - all_remove) < 1000:
                return [[]]

        if all_check is None and all_remove is None:
            return [checking]



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

Puisque la mise en page et le rappel sont liés à ʻapp de l'objet dash, il semble qu'il sera traité en passant ʻapp directement à une autre fonction.

C'est pourquoi tout en me jetant du travail dans le futur, je gratterai autant que je pourrai gratter app.py

app.py


import dash
from flask import Flask

from src.layout import layout
from src.callback import callback


server = Flask(__name__)
app = dash.Dash(__name__, server=server)

app.title = 'checklist-test'

#composants et définition de rappel
app = layout(app)
callback(app)


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

tips: L'enregistrement de rappel doit être absolument après la définition du composant Puisqu'un rappel avec une valeur d'entrée nulle s'exécute au moment de l'importation, une erreur se produira si le composant que vous regardez dans Input / Output / State n'existe pas

Composants et mise en page

Inutile de dire que veuillez changer le nom du fichier pour celui dont vous êtes satisfait.

Découpe de mise en page

Assignez l'élément html à la disposition d'attribut de ʻapp` reçu comme argument

layout.py


import dash_core_components as dcc
import dash_html_components as html


def layout(app):

    checklists = dcc.Checklist(
        id='checklist-states',
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': 'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value=['MTL', 'SF']
    )

    # app.Attribuer des éléments à la mise en page
    app.layout = html.Div(id='main', children=[
        html.H1(children='Test de la liste de contrôle'),
        dcc.Location(id='location', refresh=False),
        html.Div(className='main-block', children=[checklists]),
        html.Div(className='second', children=[
            html.Button('Tout sélectionner', id='filter-check-button', className='filter_button'),
            html.Button('Tout annuler', id='filter-remove-button', className='filter_button')
        ])
    ])

    return app

Coupure de rappel

tips: Si vous essayez d'appeler ʻupdate_check directement, la partie décorateur ne peut pas être bien interprétée, vous devez donc aller plus loin et enfermer chaque décorateur dans une autre fonction. (En bref, ʻapp of@ app.callback ()doit être capable de résoudre le nom)

callback.py


from dash.dependencies import Input, Output, State

import time


def callback(app):

    @app.callback(
        [
            Output('checklist-states', 'value')
        ],
        [
            Input('filter-check-button', 'n_clicks_timestamp'),
            Input('filter-remove-button', 'n_clicks_timestamp')
        ],
        [
            State('checklist-states', 'value')
        ]
    )
    def update_check(all_check, all_remove, checking):

        if all_check is not None:
            if (time.time() * 1000 - all_check) < 1000:
                return [['NYC', 'MTL', 'SF']]

        if all_remove is not None:
            if (time.time() * 1000 - all_remove) < 1000:
                return [[]]

        if all_check is None and all_remove is None:
            return [checking]

Que faire lorsque vous avez plus de composants et de rappels

Division supplémentaire des composants

Gérez le titre, la liste de contrôle et le bouton séparément En supposant que la mise en page ne gère que les blocs et l'espacement

tips: L'attribut ʻid n'est pas requis pour html.Div () `

layout.py


from src.components import title, checklist, button

import dash_core_components as dcc
import dash_html_components as html


def layout(app):

    app.layout = html.Div(id='main', children=[

        html.Div(id='title-block', children=[title.layout()]),

        dcc.Location(id='location', refresh=False),

        html.Div(id='center-block', children=[
            html.Div(children=checklist.layout()),
            html.Div(children=button.layout())
        ])
    ])

    return app

title.py


import dash_html_components as html


def layout():

    return html.H1(id='title', children='Test de la liste de contrôle')

checklist.py


import dash_core_components as dcc


def layout():

    return dcc.Checklist(
        id='checklist-states',
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': 'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value=['MTL', 'SF']
    )

button.py


import dash_html_components as html


def layout():

    return html.Button('Tout sélectionner', id='filter-check-button', className='filter_button'), html.Button('Tout annuler', id='filter-remove-button', className='filter_button')

Division supplémentaire du rappel

Découpez pour chaque fonction de la même manière

callback.py

from src.callbacks import check_and_remove # hoge, fuga...

def callback(app):

    check_and_remove.register(app)
    # hoge.register(app)
    # fuga.register(app)

check_and_remove.py

from dash.dependencies import Input, Output, State

import time


def register(app):

    @app.callback(
        [
            Output('checklist-states', 'value')
        ],
        [
            Input('filter-check-button', 'n_clicks_timestamp'),
            Input('filter-remove-button', 'n_clicks_timestamp')
        ],
        [
            State('checklist-states', 'value')
        ]
    )
    def update_check(all_check, all_remove, checking):

        if all_check is not None:
            if (time.time() * 1000 - all_check) < 1000:
                return [['NYC', 'MTL', 'SF']]

        if all_remove is not None:
            if (time.time() * 1000 - all_remove) < 1000:
                return [[]]

        if all_check is None and all_remove is None:
            return [checking]

Structure finale

.
├── app.py
└── src
    ├── callback.py
    ├── callbacks
    │   └── check_and_remove.py
    ├── components
    │   ├── button.py
    │   ├── checklist.py
    │   └── title.py
    └── layout.py

Recommended Posts

Supprimez les composants et les rappels de app.py avec plotly Dash
Extraire le texte du pdf [python] et lire les caractères à haute voix avec Open-Jtalk
Extraire des tables de base de données avec CSV [connexion ODBC de R et python]
[Traitement du langage naturel] Extraire les mots-clés de la base de données Kakenhi avec MeCab-ipadic-neologd et termextract
Extraire des images des ensembles de données Cifar et CUCUMBER-9
Extraire du texte japonais d'un PDF avec PDFMiner
Extraire des données d'une page Web avec Python
Extraire des images et des tableaux de pdf avec python pour réduire la charge de reporting