Session du 30/11/2020: développement d’applications web avec python et les librairies Dash et Flask
https://forgemia.inra.fr/gdtpyr/gdt_pyr/-/tree/main/GDT_PyR15_Applications_web
Cet session est un complément à la session du 14/10/2019:
https://forgemia.inra.fr/gdtpyr/gdt_pyr/-/tree/main/GDT_PyR9_devAppWeb
Introduction
L’objectif de ce document est de présenter la création d’applications web depuis Python, en utilisant les technologies Flask et Dash. Ces deux technologies sont bien liées car Dash utilise le moteur de Flask pour construire la base de l’appli web, puis rajoute l’interaction avec le langage javascript.
Flask et Dash sont parmi les plus utilisés pour créer des applications Python. On peut aussi retrouver Django.
La documentation officielle est ici:
https://flask.palletsprojects.com/en/1.1.x/
https://flask.palletsprojects.com/en/1.1.x/quickstart/#routing
https://flask.palletsprojects.com/en/1.1.x/quickstart/#accessing-request-data
https://docs.djangoproject.com/en/3.1/
https://plotly.com/dash/
https://dash.plotly.com/dash-enterprise/application-structure
https://dash.plotly.com/dash-core-components
https://dash.plotly.com/dash-html-components
https://dash.plotly.com/datatable
https://dash.plotly.com/dash-bio
https://dash.plotly.com/cytoscape
https://dash-bootstrap-components.opensource.faculty.ai/
Installation des packages
Pensez aux environnements virtuels (conda/venv).
pip install Flask
pip install dash
pip install dash-renderer
pip install dash-html-components
pip install dash-core-components
pip install plotly --upgrade
Framework Dash
Dash est un framework Python pour construire des applications web analytiques. Les applications Dash sont entièrement générées à partir de Python, même le code HTML et JavaScript. C’est une framework composé de trois frameworks : - React.js : utilise un système de plugins pour créer ses propres composants - Plotly : créer la partie frontend avec des outils UI de data visualisation - Flask : framework écrit en python pour le backend.
Flask est plus utilisé quand on a des connaissances dans plusieurs langages. Dash est plus général et est basé sur Flask (qui sera présenté plus tard). Dash est pratique car il ne nécessite pas de connaître d’autres langages que python grâce à ses différentes librairies.
- Dash Core Components : pour les composants de l’interface utilisateur (création de liste déroulante, curseur…)
import dash_core_components as dcc
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': 'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'}
],
value='MTL'
)
- Dash HTML Component : pour composer la structure HTML de l’application.
import dash_html_components as html
html.Div([
html.H1('Hello Dash'),
html.Div([
html.P('Dash converts Python classes into HTML'),
html.P('This conversion happens behind the scenes by Dash's JavaScript front-end')
])
])
- Dash DataTable : pour ajouter des tableaux de données mais aussi pouvoir explorer et modifier de grands jeux de données.
import dash
import dash_table
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')
app = dash.Dash(__name__)
app.layout = dash_table.DataTable(
id='table',
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict('records'),
)
if __name__ == '__main__':
app.run_server(debug=True)
- Dash Bootstrap Components : des composants Bootstrap pour Dash pour construire plus facilement la disposition de l’application.
pip install dash-bootstrap-components
import dash
import dash_bootstrap_components as dbc
app = dash.Dash(
external_stylesheets=[dbc.themes.BOOTSTRAP]
)
app.layout = dbc.Alert(
"Hello, Bootstrap!", className="m-5"
)
if __name__ == "__main__":
app.run_server()
- Dash Bio : un ensemble de composants bioinformatique qui permet de simplifier la visualisation et traitement des données dans ce domaine.
import dash_bio as dashbio
import six.moves.urllib.request as urlreq
data = urlreq.urlopen(
"https://raw.githubusercontent.com/plotly/dash-bio-docs-files/master/" +
"alignment_viewer_p53.fasta"
).read().decode("utf-8")
component = dashbio.AlignmentChart(
id='my-dashbio-alignmentchart',
data=data
)
- Dash Cytoscape : pour le traitement et visualisation de données de graphes.
pip install dash-cytoscape==0.2.0
import dash
import dash_cytoscape as cyto
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div([
cyto.Cytoscape(
id='cytoscape-two-nodes',
layout={'name': 'preset'},
style={'width': '100%', 'height': '400px'},
elements=[
{'data': {'id': 'one', 'label': 'Node 1'}, 'position': {'x': 75, 'y': 75}},
{'data': {'id': 'two', 'label': 'Node 2'}, 'position': {'x': 200, 'y': 200}},
{'data': {'source': 'one', 'target': 'two'}}
]
)
])
if __name__ == '__main__':
app.run_server(debug=True)
Architecture pour Dash
L’architecture d’une application Dash est assez simple :
Dash_App/
|-- assets/
|-- app.css
|--data
|-- data.csv
|-- app.py
|-- .gitignore
|-- CHECKS
|-- Procfile
|-- requirements.txt
|-- runtime.txt
app.py : c’est là où se trouve l’application avec le code Dash. Il doit contenir une ligne pour définir le server (server = app.server).
data : dossier contenant fichier de données (csv, txt, …), que l’on peut utiliser de la manière suivante:
import pandas as pd
df = pd.read_csv('data/data.csv', index_col=0, parse_dates=True)
df.index = pd.to_datetime(df['Date'])
- .gitignore : détermine quels fichiers et dossiers qui ne sont pas encore dans git (donc ignoré par le server au moment du déploiement).
- assets : dossier facultatif qui peut contenir des fichiers css ou javascript pour compléter l’application
- CHECKS : fichier optionnel qui peut être exécuté pour vérifier les performances de l’application.
- Procfile : les commandes qui vont être exécutées par le conteneur de l’application.
- requirements.txt : les installations nécessaires pour l’application
- runtime.txt : fichier optionnel pour préciser la version de python à utiliser (par défaut pyhon 3.6.7 est installé)
Importation de données web service
Possibilité de se connecter et récupérer des données de web service à utiliser dans les applis web. Cf. code dans la version déposée sur GdT-PyR.
Deploiement
Il y a un petit moteur de déploiement qui permet un déploiement de développement, c’est à dire pour voir ce qu’on fait pendant le développement de l’application. Ce moteur supporte mal le passage à l’échelle (voir un GDT-PyR prochain!).
$ export FLASK_APP=main.py
$ flask run
* Running on http://127.0.0.1:5000/
En alternative, il suffit d’executer le fichier et de s’assurer que celui-ci se termine par la ligne suivante :
if __name__ == "__main__":
app.run(host = '0.0.0.0', debug = True, threaded = True, port = 3838)
Déploiement par Docker… Objet de futures GDT_PyR 16 et 17
Je peux vous proposer un aperçu de mon travail https://github.com/JeanEudesH/uri-generator qui est une appli basée sur Flask.
Architecture générale d’une appli avancée
Exemple complet ici : https://hackersandslackers.com/plotly-dash-with-flask/
dash + flask. Attention c’est assez dur, il est conseillé de prendre l’approche “classique” pas à pas avant de se lancer là-dedans.
Découpé en fonctions
- appli dans /app
- fichier de commandes lancement (.sh)
- déploiement wsgi
- fichier de config -> lecture du fichier .env (caché) + configuration packages-répertoires
- Documentation + packages utilisés
- On peut rajouter Dockerfile pour déploiement container
/plotlydash-flask-tutorial
├── /app
│ ├── __init__.py
│ ├── routes.py
│ ├── /static
│ ├── /templates
│ └── /plotlydash
│ └── dashboard.py
├── /data
├── README.md
├── config.py
├── requirements.txt
├── start.sh
└── wsgi.py
Comment écrire une app
L’architecture classique d’une application est la suivante :
On rentrera dans les détails au fur-et-à mesure.
On va détailler le fichier main.py. C’est le coeur de l’application, il fonctionne de manière autonome. Le reste c’est pour rendre plus “joli”, plus efficace et d’autres fonctions.
Différentes pages
On définit des “routes”, ce sont les adresses URL. Lorsque l’on navigue vers ces adresses, la fonction se déclenche et retourne un résultat.
HTTP Methods
Il y a deux principales interactions les “GET”, où on récupère des données depuis le serveur, et les POST où on envoie des données vers le serveur. Les GET sont principalement des affichages de pages et formulaires. Les POST sont les envois de ces dit formulaires, et la soumission de jeux de données.
Templates
On veut quand même des pages un peu plus jolies avec de la vraie mise en page. Pour ça on utilise des templates HTML. Et on dit à Flask d’aller chercher ces pages et de nous les renvoyer. On peut aussi écrire du HTML directement dans le “return” de la fonction, mais c’est pas très propre. On détaille ici le rôle du dossier “templates” de l’architecture de l’appli. C’est ici que l’on place nos différents templates qui constituent différentes pages de notre application.
Je me suis permis aussi d’introduire l’objet “session”, qui sont les fameux cookies que les sites webs vous demandent sans arrêt. C’est un moyen de stocker et transférer de l’informations d’une session à la suivante. L’objet session va se différencier de l’objet cookies par la signature crytographique qui lui est apportée. Cela demande de définir une clé de cryptage pour l’application. (voir fichier “.env” pour le garder secret)
Accéder aux données
Une fois qu’on a soumis un formulaire, on veut que python puisse utiliser ces données. Pour cela on utilise l’objet “request”. C’est l’objet qui est transmis lors du “POST”.
Il faut donc faire le lien entre le formulaire HTML et la requête dans python. Ce lien se fait par le nom du formulaire et des composants “INPUT”, “SELECT” etc.