Vous êtes sur la page 1sur 49

J'ai toutefois essayé à chaque fois de ne pas réinventer la roue.

Badiou OURO-BANG’NA

COURS DE
DEVELOPPE-
MENT PY-
THON AVEC LE
FRAMEWORK
FLASK
MISE EN PLACE DES API (APPLICATION PROGRAM-
MING INERFACE) AVEC UN FRAMEWORK PYTHON
(Flask)

OURO-BANG’NA Badiou, Full-Stack Developer


27/10/2021
OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Ce cours est adressé aux personnes désireuses d’apprendre le développement


python Flask.

OURO-BANG’NA Badiou
Le volume horaire pour terminer ce cours est de 24h – 30h

Prérequis : Afin de suivre ce cours, il y a certains prérequis nécessaires.


- Conception MERISE, UML
- Connaissances de bases de Python
- Bases de données
- PostgreSQL

Contenu du cours

Partie 1 (15 heures) :


SQL et Modélisation de données pour le Web
 Présentation du cours : Généralités de Python

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 1


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

 Interagir avec les bases de données


 Bases de SQLAlchemy
 SQLAlchemy ORM en profondeur
 Construire une application CRUD avec SQLAlchemy ORM 1
 Migrations
 Construire une application CRUD avec SQLAlchemy ORM 2

Partie 2 (12 heures): Python Flask Framework


Développement et documentation d’API
 Introduction aux API
 Principe de bases HTTP & FLASK
 Endpoints de l’API & Payloads
 Test d’API
 Documentation de l’API

Partie 3 (1h) : Gestion des authentification et


autorisations: Sécurisation des API
 Fondamentaux de la sécurisation des API
 Identité et authentification
 Mots de passes
 Gestion des accès et autorisations
 Documentation des API

Partie 4 (2h) : Déploiement des API


 Cette parie concerne juste une démonstration vidéo permettant de montrer à chaque étudiant
comme déployer par exemple son A.
 Présentation de l’API par chaque étudiant.

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 2


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 3


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Table des matières


1. Éditeur de code.......................................................................................................................... 7
a- Utilisateurs Linux/Mac ...................................................................................................... 7
b- Utilisateurs Windows ......................................................................................................... 7
1- Bases de données relationnelles .......................................................................................... 8
2- Les systèmes de gestion de bases de données .................................................................... 8
3- Clé primaire ......................................................................................................................... 9
4- Clé étrangère ........................................................................................................................ 9
5- SQL : Structured Query Language ................................................................................... 9
Accéder au serveur de base de données ......................................................................................... 12
Quelques commandes à lancer dans le terminal : .......................................................................... 13
- Installation de pyscopg2 ......................................................................................................... 13
- Psycopg2 : Utilisation de base ................................................................................................ 14
1- Qu’est-ce que SQLAlchemy ? ............................................................................................. 15
2- Les couches d’abstraction de SQLAlchemy ....................................................................... 16
3- Classes Python et Tables de la base de données .................................................................. 17
4- Installation de Flask et SQLAlchemy ................................................................................. 18
5- Importer Flask et SQLAlchemy .......................................................................................... 18
6- Votre première application python Flask............................................................................. 18
- Initialisation de l'application ............................................................................................... 18
- Utilisation de @app.route.................................................................................................... 18
- Exécuter l'application Flask ................................................................................................ 19
7- Connexion à la base de données .......................................................................................... 19
8- Modèles et définitions des modèles..................................................................................... 20
9- Expérimenter le mode interactif .......................................................................................... 20
En résumé ................................................................................................................................... 21
10- Les types de données ........................................................................................................... 21
11- Contraintes : One to Many 1-N ........................................................................................... 22
12- Contrainte Many to Many (m,n).......................................................................................... 22
Méthodes de requête ...................................................................................................................... 22
Sélectionner des enregistrements ............................................................................................... 22
Commande ................................................................................................................................. 23
Agrégats ..................................................................................................................................... 23
Requêtes de jointure ....................................................................................................................... 24
Analogie entre les commandes SQL et les commandes de l’ORM ............................................... 24
S'entraîner ...................................................................................................................................... 30

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 4


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Code de démarrage..................................................................................................................... 30
Installation de Flask-Migrate ......................................................................................................... 34
Exemple de migration de données ................................................................................................. 34
Ce que peut faire une api concrètement ............................................................................. 37
1- Structure d’une requête http ................................................................................................ 38
2- Liste des méthodes .............................................................................................................. 38
3- Liste des réponses http (Status Code).................................................................................. 39
4- Les Status code les plus connus : ........................................................................................ 39
1- Commande curl ................................................................................................................... 40
2- Utilisation de Postman......................................................................................................... 40

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 5


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Partie I :

SQL et Modélisation de
données pour le Web

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 6


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Voici les compétences dont vous aurez besoin pour ce cours :


1. Programmation de base en Python
2. Notions de base sur les commandes de terminal
3. Bases de données SQL et relationnelles.

Besoin d'un rafraîchissement sur ceux-ci? Découvrez ces cours et les programmes Nanodegree.
1. Introduction à la programmation Python
2. Atelier Shell (ligne de commande) ou principes de base de la ligne de commande Linux
3. SQL pour l'analyse de données et introduction aux bases de données relationnelles

Et voici la pile technologique dans laquelle nous allons gagner en maîtrise :


1. Python 3
2. Flask
3. PostgreSQL
4. Psycopg2
5. SQLAlchemy
6. Flask-SQLAlchemy

Outils requis
Avant de commencer, assurons-nous que tous les outils nécessaires sont installés. Elles sont:
1. Un éditeur de code
2. Une interface de ligne de commande (CLI) comme Terminal ou GitBash.
3. Python v3.7+ et gestionnaire de packages Python pip
4. Un navigateur Internet

1. Éditeur de code
Vous avez probablement déjà un éditeur de code installé sur votre ordinateur ; sinon, vous aurez besoin
d'en obtenir un maintenant pour suivre avec nous pour le reste de ce cours. Je préfère Visual Studio
Code (VS Code)
2. Interface de ligne de commande (CLI)
Les vidéos de démonstration de ce cours utilisent quelques commandes Linux et Git. Vous devez donc
disposer d'une interface de ligne de commande (CLI) capable d'exécuter des commandes Linux et Git.

a- Utilisateurs Linux/Mac
Linux et Mac OS ont une CLI intégrée appelée "Terminator" ou "Terminal", respectivement, qui prend
en charge la plupart des commandes Linux et Git. Vous n'avez pas besoin d'installer d'autre CLI.

b- Utilisateurs Windows
La CLI par défaut dans Windows est CMD (Invite de commandes). Par défaut, CMD ne peut exécuter ni
Linux ni aucune commande Git. Par conséquent, vous avez besoin d'un moyen d'activer l’environne-
ment Linux sur Windows. L'une des options consiste à utiliser l’outils de ligne de commande Git Bash,
fourni par Git. Git Bash est installé lorsque vous installez Git pour Windows .

c- Vérification de l’installation de python

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 7


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

A- Interagir avec la base de données


1- Bases de données relationnelles

Il est difficile de donner une définition exacte de la notion de base de données. Une définition très générale
pourrait être : Un ensemble organisé d'informations avec un objectif commun.

Peu importe le support utilisé pour rassembler et stocker les données (papier, fichiers, etc.), dès lors que
des données sont rassemblées et stockées d'une manière organisée dans un but spécifique, on parle de base
de données.

Plus précisément, on appelle base de données un ensemble structuré et organisé permettant le stockage de
grandes quantités d'informations afin d'en faciliter l'exploitation (ajout, mise à jour, recherche de don-
nées). Bien entendu, dans le cadre de ce cours, nous nous intéressons aux bases de données informatisées.

Une base de données relationnelle est une base de données structurée suivant les principes de l'algèbre
relationnelle.

Le père des bases de données relationnelles est Edgar Frank Codd. Chercheur chez IBM à la fin des années
1960.

2- Les systèmes de gestion de bases de données

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 8


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

3- Clé primaire
- La clé primaire est l'identifiant unique de toute la ligne, faisant référence à une ou plusieurs co-
lonnes.
- S'il existe plusieurs colonnes pour la clé primaire, l'ensemble de colonnes de clé primaire est ap-
pelé clé composite.

4- Clé étrangère
- Une clé primaire dans une autre table (étrangère).
- Les clés étrangères sont utilisées pour mapper les relations entre les tables.

Exemple de modèle conceptuel de bases de données

5- SQL : Structured Query Language

 SELECT - Sélectionner des données.


 UPDATE - Mettre à jour les données
 DELETE - Supprimer les données
 INSERT INTO - Insérer les données
 CREATE DATABASE - Créer une base de données
 ALTER DATABASE - Modifier une base de données
 CREATE TABLE - Créer une table
 ALTER TABLE - Modifier une table

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 9


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

 DROP TABLE - Supprimer une table


 CREATE INDEX – Créer un index
 DROP INDEX – Supprimer un index.

Questions :

1- Vrai/Faux : Chaque système de base de données relationnelle a sa propre implémentation


particulière de SQL………………………. Réponse VRAI
2- Différents systèmes de bases de données relationnelles ont différentes « saveurs » de
SQL ; chacune de ces variétés est appelée…………………. Réponse DIALECT
3- Quelle commande utiliser pour sélectionner une information dans une
table ?..................Réponse SELECT

B- Architecture client serveur


Afin de créer des applications Web basées sur des bases de données, nous devons d'abord comprendre
comment les serveurs, les clients et les bases de données interagissent.
Une partie importante de ceci est l’architecture client-serveur, alors examinons-le d'abord. L'idée de
base est très simple et ressemble à ceci :

- Un serveur est un programme centralisé qui communique sur un réseau (comme Internet)
pour servir les clients.
- Un client est un programme (comme le navigateur Web de votre ordinateur) qui peut de-
mander des données à un serveur. Lorsque vous accédez à une page Web dans votre naviga-
teur, votre navigateur (le client) fait une demande au serveur, qui renvoie ensuite les don-
nées de cette page.
-

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 10


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Serveurs, clients, hôtes


- Dans un modèle client-serveur, un serveur sert de nombreux clients.
- Les serveurs et les clients sont des programmes qui s'exécutent sur des hôtes.
- Les hôtes sont des ordinateurs connectés sur un réseau (comme Internet !).

Requêtes et réponses
- Un client envoie une requête au serveur
- Le travail du serveur est de répondre à la demande avec une réponse qu'il renvoie au client.
- Les demandes et les réponses sont servies via un protocole de communication, qui définit les
attentes et les règles relatives à la manière dont la communication se produit entre les serveurs et
les clients.

Clients de base de données relationnelle

Un client de base de données est tout programme qui envoie des requêtes à une base de données
Dans certains cas, le client de base de données est un serveur Web ! Lorsque votre navigateur fait une
demande, le serveur Web agit en tant que serveur (répondant à cette demande), mais lorsque le serveur
Web demande des données à la base de données, il agit en tant que client pour cette base de données—et
la base de données est le serveur (car elle répond à la demande).
Ne laissez pas cela vous embrouiller. Fondamentalement, nous appelons les choses des clients lorsqu'ils
font une demande et des serveurs lorsqu'ils répondent à une demande. Étant donné qu'un serveur Web
peut faire les deux, il agit parfois en tant que serveur et parfois en tant que client.

C- TCP/IP
TCP/IP désigne communément une architecture réseau, mais cet acronyme désigne en fait 2 protocoles
étroitement liés : un protocole de transport, TCP (Transmission Control Protocol) qu’on utilise « par-des-
sus » un protocole réseau, IP (Internet Protocol). Ce qu’on entend par « modèle TCP/IP », c’est en fait
une architecture réseau en 4 couches dans laquelle les protocoles TCP et IP jouent un rôle prédominant,
car ils en constituent l’implémentation la plus courante. Par abus de langage, TCP/IP peut donc désigner
deux choses : le modèle TCP/IP et la suite de deux protocoles TCP et IP.

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 11


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

TCP/IP utilise :

- Adresses IP : Une adresse IP identifie l'emplacement d'un ordinateur sur un réseau.


- Ports : Un port est un emplacement sur l'ordinateur destinataire, où les données sont reçues.
Alors qu'une adresse IP vous indique où trouver un ordinateur particulier, elle ne vous dit pas spéci-
fiquement où sur cet ordinateur une connexion particulière doit être établie - c'est à cela que servent
les numéros de port.
Quelques numéros de port à connaître :
- Port 80 : Le numéro de port le plus couramment utilisé pour les requêtes HTTP. Par exemple,
lorsqu'un client fait une demande à un serveur Web, cette demande est généralement envoyée
via le port 80.
- Port 5432 : Le numéro de port utilisé par la plupart des systèmes de base de données ; port par
défaut pour PostgreSQL.

1. TCP/IP est basé sur la connexion, ce qui signifie que toutes les communications
entre les parties sont organisées via une connexion. Une connexion est établie avant
le début de toute transmission de données.
2. Sur TCP/IP, nous aurons toujours besoin d’établir une connexion entre les clients et
les serveurs afin de permettre les communications. De plus:
3. Les livraisons via la connexion font l'objet d’un contrôle d'erreur : si des paquets
arrivent endommagés ou perdus, ils sont alors renvoyés (appelé retransmission).
4. La connexion démarre une session. Mettre fin à la connexion met fin à la session.
5. Dans une session de base de données, de nombreuses transactions peuvent se pro-
duire au cours d'une session donnée. Chaque transaction fonctionne pour valider les
modifications apportées à la base de données (mise à jour, insertion ou suppression
d'enregistrements).

D- Installation de PostgreSQL
Avant de pouvoir utiliser Postgres, nous devons l'installer. Vous avez peut-être déjà Postgres, par
exemple si vous êtes un utilisateur de MacOS, il est déjà installé sur votre machine. Mais juste au
cas où, voici quelques étapes pour le télécharger et l'installer.
Aller à la Postgres Télécharger la page et télécharger Postgres pour votre machine.

1. Pour MacOS, Postgres est déjà téléchargé. Homebrew est une voie populaire pour
installer Postgres. Voir cet aperçu sur l'installation de Postgres via Brew .

2. Sous Linux, vous pouvez exécuter apt-get install postgresql.

3. Pour Windows, téléchargez le programme d'installation à partir de la page de télé-


chargement de la base de données PostgreSQL . Le programme d'installation instal-
lera PostgreSQL server et pgAdmin , une interface graphique pour gérer les bases
de données Postgres.

Accéder au serveur de base de données


Linux : sudo su – postgres puis psql
Windows : psql -U postgres ou psql – d database –U user

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 12


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Quelques commandes à lancer dans le terminal :


# \l : Répertorier toutes les bases de données sur le serveur, leurs propriétaires et les niveaux d'ac-
cès des utilisateurs
# \c <dbname> : Connectez-vous à une base de données nommée
# \dt : Afficher les tables de la base de données
# \d <tablename> : Décrire le schéma de la table
# \q : Quittez psql, retournez au terminal
# \? : Obtenir de l'aide, voir la liste des commandes disponibles.

Les autres clients Postgres

- pgAdmin : disponible pour chaque système d'exploitation


- PopSQL : disponible pour MacOS
- PostBird : disponible pour chaque système d'exploitation

E- DBAPI
Nous voudrons parfois interagir avec notre base de données et utiliser ses résultats dans un langage
de programmation spécifique. Par exemple pour construire des applications Web ou des pipelines
de données dans un langage spécifique (Ruby, Python, Javascript, etc.). C'est là qu'interviennent les
DBAPI.
Une DBAPI :
- Fournit une interface standard pour un langage de programmation (comme Python) pour
parler à un serveur de base de données relationnelle.
- Est une bibliothèque de bas niveau pour écrire des instructions SQL qui se connectent à une
base de données
- Est également connu sous le nom d'adaptateurs de base de données.

Exemples à travers les langues et les frameworks de serveur


 Pour Ruby (par exemple pour Sinatra, Ruby on Rails): pg
 Pour NodeJS : node-postgres
 Pour Python (par exemple pour Flask, Django): pyscopg2
psycopg2 est au centre de ce cours puisque nous utilisons une pile Python.

- Installation de pyscopg2

python –version

pip install pyscopg2

 Si l'installation normale ne fonctionne pas, vous pouvez également simplement installer la version
binaire à la place :

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 13


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

pip install psycopg2-binary

qui remplace la nécessité de courir pip install pyscopg2


- Psycopg2 : Utilisation de base
import psycopg2

conn = psycopg2.connect('dbname=todoapp_development user=amy')

cursor = conn.cursor()

# Open a cursor to perform database operations


cur = conn.cursor()

# drop any existing todos table


cur.execute("DROP TABLE IF EXISTS todos;")

# (re)create the todos table


# (note: triple quotes allow multiline text in python)
cur.execute("""
CREATE TABLE todos (
id serial PRIMARY KEY,
description VARCHAR NOT NULL );""")

# commit, so it does the executions on the db and persists in the db


conn.commit()

cur.close()
conn.close()

import psycopg2

connection = psycopg2.connect('dbname=example')

cursor = connection.cursor()

cursor.execute('DROP TABLE IF EXISTS table2;')

cursor.execute('''
CREATE TABLE table2 (
id INTEGER PRIMARY KEY,
completed BOOLEAN NOT NULL DEFAULT False
);
''')

cursor.execute('INSERT INTO table2 (id, completed) VALUES (%s, %s);', (1, True))

SQL = 'INSERT INTO table2 (id, completed) VALUES (%(id)s, %(completed)s);'

data = {
'id': 2,
'completed': False
}
cursor.execute(SQL, data)

connection.commit()

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 14


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

connection.close()
cursor.close()

F- Les bases de SQLAlchemy


1- Qu’est-ce que SQLAlchemy ?

 SQLAlchemy est la bibliothèque open source la plus populaire pour travailler avec les bases de
données relationnelles de Python.
 C'est un type de bibliothèque ORM , AKA une bibliothèque de Object-Relational Mapping, qui
fournit une interface pour utiliser la programmation orientée objet pour interagir avec une base de
données.

D’autres lanages de programmation utilisent aussi des ORM comme Eloquent pour Laravel PHP,
EntityFramework pour ASP.NET etc….

Pourquoi utiliser une ORM ?

- Permet de faire abstraction du SGBD utilisé dans l’écriture du code.


- Permet de travailler facilement et entièrement dans le langage utilisé (Python) dans notre cas
plutôt que d’écrire du SQL brut.
- Ecrire du code sujet à moins de bugs
- Mapper directement les tables de la base de données aux attributs de la classe
- Etc….

Question : Ce code ci-dessous fonctionnera-t-il pour tous les SGBD ?

CREATE TABLE products (


id INTEGER PRIMARY KEY,
description VARCHAR NOT NULL
);

Réponse : Non. D’où l’utilité d’utiliser une ORM

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 15


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

2- Les couches d’abstraction de SQLAlchemy

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 16


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

3- Classes Python et Tables de la base de données

SQL SQLAlchemy
CREATE TABLE tweets ( Class Tweet :
id INTEGER PRIMARY KEY, def __init__(self,content) :
content VARCHAR(140) NOT NULL self.content=content
);

INSERT INTO tweets (content) VALUES ('he Tweet=Tweet(content=’hey’)


y!');

Alors :
- Les tables correspondent aux classes (SQLAlchemy)
- Les enregistrements de tables sont mappés sur les objets

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 17


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

- Les colonnes du tableau correspondent aux attributs

4- Installation de Flask et SQLAlchemy


- Pour installer Flask : pip3 install flask
- Pour installer SQLAlchemy : pip3 install flask-sqlalchemy

NB : Si pip3 ne marche pas utilisez pip.

5- Importer Flask et SQLAlchemy


from flask import Flask
from flask_sqlalchemy import SQLAlchemy

6- Votre première application python Flask

from flask import Flask


from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']='postgresql://postgres:@localhost:5432/mabase
'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db=SQLAlchemy(app)

class Person(db.Model):
__tablename__ = 'persons'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), nullable=False)

db.create_all()
@app.route('/')
def index():
return 'Je suis dans la joie!'

app.config['SQLALCHEMY_DATABASE_URI'] = database_path

- Initialisation de l'application
app = Flask(__name__) définit le nom de votre application sur le nom de votre module ("app" si
"app.py" est le nom de votre fichier).

- Utilisation de @app.route
@app.route('/')
def index():
...

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 18


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Dans ce cas, @app.route est un décorateur Python .


Les décorateurs prennent des fonctions et renvoient une autre fonction, étendant généralement la
fonction d'entrée avec des fonctionnalités supplémentaires ("décorées"). @app.route est un décora-
teur qui prend une fonction d'entrée index() comme rappel qui est invoqué lorsqu'une demande de
routage / provient d'un client.
Voir : cette introduction aux décorateurs de Real Python .

- Exécuter l'application Flask

Pour démarrer le serveur en utilisant 3 commandes :


Sous Linux :
export FLASK_APP=app.py
export FLASK_ENV=development
flask run

Sous Windows :
set FLASK_APP=app.py
set FLASK_ENV=development
flask run

7- Connexion à la base de données

from flask import Flask


from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://toto@localhost:5432/example'
db = SQLAlchemy(app)

- Exemple de chaine de connexion :

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 19


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

8- Modèles et définitions des modèles


 Déclarer des classes :

Pour approfondir vos connaissances, consulter le lien : https://flask-sqlalchemy.palletspro-


jects.com/en/2.x/models/

class MyModel(db.Model) héritera de db.Model


En héritant de db.Model , nous mappons de nos classes vers des tables via SQLAlchemy ORM
 Définition des colonnes :
Dans notre classe, nous déclarons des attributs égaux à db.Column(...)
db.Column prend <datatype>, <primary_key?>, <constraint?>, <default?>

 Nommage des tables


Par défaut, SQLAlchemy choisira le nom de la table pour vous, en le définissant égal à la version
minuscule du nom de votre classe. Sinon, nous définissons le nom de la table à l'aide de
__tablename__ = 'my_custom_table_name' .

from flask import Flask


from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://test@localhost:5432/example'
db = SQLAlchemy(app)

class Person(db.Model):
__tablename__ = 'persons'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), nullable=False)
db.create_all()

@app.route('/')
def index():
person = Person.query.first()
return 'Hello ' + person.name

9- Expérimenter le mode interactif


Le mode interactif consiste à lancer la commande python ou python3 dans le terminal.
Exemple :

$ python3
>>> from flask_hello_app import Person, db

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 20


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

>>> Person.query.all()
>>> Person.query.first()
>>> query = Person.query.filter(Person.name == 'OURO-BANG\’NA Badiou')
>>> query.first()
>>> query.all()

Ensuite, créez une instance de person, en définissant ses attributs et en lui donnant la valeur d'une
variable person

>>> person = Person(name='Badiou')


Nous allons appeler db.session.add() , une méthode sur l'interface Session dans SQLAlchemy,
pour ajouter cet objet à une session,

>>> db.session.add(person)
Cela mettra en file d'attente une INSERT INTO persons (name) VALUES ('Badiou');
instruction dans une transaction gérée par db.session .
On peut alors appeler db.session.commit()

>>> db.session.commit()
et cet enregistrement de personne existera désormais dans notre persons table, dans notre base de
données ! Vous pouvez vérifier cela dans psql en exécutant une SELECT * from persons; com-
mande à partir de psql.

En résumé
Nous pouvons insérer de nouveaux enregistrements dans la base de données en utilisant
SQLAlchemy en exécutant :

person = Person(name='Amy')
db.session.add(person)
db.session.commit()
qui construira une transaction à insérer dans une instance de person de notre modèle/table et la vali-
dera l’enregistrement dans la base de données lors de l'appel de commit() .

10- Les types de données


https://flask-sqlalchemy.palletsprojects.com/en/2.x/models/

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 21


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

11- Contraintes : One to Many 1-N

12- Contrainte Many to Many (m,n)

G- Requêtes avec SQLAlchemy

Méthodes de requête
Voici quelques méthodes de requête utiles à connaître.

Sélectionner des enregistrements

all()
MyModel.query.all()
Même chose que faire un SELECT * , récupérer tous les enregistrements de la table du modèle. Ren-
voie une liste d'objets.

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 22


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

first()
MyModel.query.first()
Récupère uniquement le premier résultat. Renvoie l'un None ou l' autre ou un objet s'il est trouvé

Filter_by
MyModel.query.filter_by(my_table_attribute='some value')
Similaire à l'exécution d'une SELECT * from ... WHERE instruction SQL pour selectionner les don-
nées par attributs nommés.

filter
Exemples:

MyModel.query.filter(MyOtherModel.some_attr='some value')
OrderItem.query.filter(Product.id=3)

Similaire à filter_by , vous spécifiez des attributs sur un modèle donné. Il est plus flexible que
l'utilisation filter_by lui-même et est particulièrement utile lors d'une requête à partir d'une table
jointe où vous souhaitez filtrer par attributs qui s'étendent sur plusieurs modèles.

Attendez... il n'y a plus qu'à filtrer !

Vous pouvez filtrer sur l'égalité, l'inégalité, comme le filtrage (correspondance de chaîne "fuzzy"),
IN, NOT IN, NULL, NOT NULL, etc. Assurez-vous de consulter la référence de la documentation
SQLAlchemy sur les opérateurs de filtrage courants ici .

Commande

Order_by
MyModel.order_by(MyModel.created_at)
MyModel.order_by(db.desc(MyModel.created_at))
Pour ordonner les résultats par un attribut donné. Utilisez db.desc pour ordonner par ordre décrois-
sant.

limit
Order.query.limit(100).all()
limit(max_num_rows) limite le nombre d'enregistrements renvoyés par la requête. ala LIMIT en SQL.

Agrégats

count()
Exemple:
query = Task.query.filter(completed=True)
query.count()
Renvoie un entier défini sur le nombre d'enregistrements qui auraient été renvoyés en exécutant la
requête.

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 23


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

get()
Obtenir l'objet par ID
model_id = 3
MyModel.query.get(model_id)
Renvoie l'objet suite à l'interrogation du modèle par sa clé primaire.

Exemple:
query = Task.query.filter_by(category='Archived')
query.delete()
delete() effectue une opération de suppression en bloc qui supprime chaque enregistrement corres-
pondant à la requête donnée.

Requêtes de jointure
Exemple:
Driver.query.join('vehicules')
La requête a une méthode join(<table_name>) pour joindre un modèle à une autre table.
Récapitulatif :

H- Construire une application CRUD


Jusqu'à présent, nous avons construit une grande partie des bases conceptuelles dont nous aurions
besoin pour comprendre comment faire du développement Web dans le monde réel à travers la
pile. Dans cette prochaine série de leçons à partir de maintenant jusqu'à la fin de ce cours, nous allons
devenir très pratiques, en créant une application entièrement fonctionnelle du début à la fin.

Analogie entre les commandes SQL et les commandes de l’ORM

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 24


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

OPERATION COMMANDE SQL COMMANDE ORM


C (create) INSERT db.session.add(user)
R (Read) SELECT User.query.all()
U (Update) UPDATE User1.foo=’new value’
D (Delete) DELETE db.session.delete(user1

I- ARCHITECTURE MVC

Modèle-vue-contrôleur ou MVC est un pattern d’architecture logicielle destiné aux interfaces gra-
phiques lancé en 1978 et très populaire pour les applications web. Le motif est composé de trois
types de modules ayant trois responsabilités différentes : les modèles, les vues et les contrôleurs.

 Un modèle (Model) contient les données à afficher.


 Une vue (View) contient la présentation de l'interface graphique.
 Un contrôleur (Controller) contient la logique concernant les actions effectuées par l'utilisateur.
Ce motif est utilisé par de nombreux Framework pour applications web tels que ASP.NET
MVC, Spring, Laravel, Django, Flask ou AngularJS.

Read en utilisant des données dump:


Créer todoapp/app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
return render_template('index.html', data=[{
'description': 'Todo 1'
}, {
'description': 'Todo 2'
}, {
'description': 'Todo 3'
}])

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 25


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Créer todoapp/templates/index.html
<html>
<head>
<title>Todo App</title>
</head>
<body>
<ul>
{% for d in data %}
<li>{{ d.description }}</li>
{% endfor %}
</ul>
</body>
</html>

Code de solution à la section précédente


todoapp/app.py
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://udacitystudios@localhost:5432/todoa
pp'
db = SQLAlchemy(app)

class Todo(db.Model):
__tablename__ = 'todos'
id = db.Column(db.Integer, primary_key=True)
description = db.Column(db.String(), nullable=False)

def __repr__(self):
return f'<Todo {self.id} {self.description}>'

db.create_all()

@app.route('/')
def index():
return render_template('index.html', data=Todo.query.all())

todoapp/templates/index.html
<html>
<head>
<title>Todo App</title>
</head>
<body>
<ul>
{% for d in data %}
<li>{{ d.description }}</li>
{% endfor %}
</ul>
</body>
</html>

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 26


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Commandes de terminal exécutées :


$ create todoapp
$ FLASK_APP=app.py FLASK_DEBUG=true flask run
psql todoapp
>>> \dt
>>> \d todos
>>> INSERT INTO todos (description) VALUES ('Do a thing 1');
>>> INSERT INTO todos (description) VALUES ('Do a thing 2');
>>> INSERT INTO todos (description) VALUES ('Do a thing 3');
>>> INSERT INTO todos (description) VALUES ('Do a thing 4');
>>> select * from todos;

J- Obtenir les données utilisateurs


Il existe 3 méthodes pour obtenir des données utilisateur d'une vue vers un contrôleur. Voir l'image ci-
dessous.
- Paramètres de requête d'URL
- Formes
- JSON

Paramètres de requête d'URL


Les paramètres de requête d'URL sont répertoriés sous forme de paires clé-valeur à la fin d'une URL,
précédant un " ?" point d'interrogation. Ex www.example.com/hello?my_key=my_value .

Données de formulaire
request.form.get('<name>') lit le value à partir d'un champ de saisie de formulaire (saisie de
texte, saisie de nombre, saisie de mot de passe, etc.) par l’attribut name sur l'élément HTML d'entrée.

Remarque : valeurs par défaut


request.args.get , les request.form.get deux acceptent un second paramètre facultatif, par
exemple request.args.get('foo', 'my default') , défini sur une valeur par défaut, au cas où le
résultat serait vide.

JSON
request.data récupère JSON sous forme de chaîne . Ensuite, nous prendrions cette chaîne et la trans-
formerions en python en appelant json.loads la request.data chaîne pour la transformer en listes
et dictionnaires en Python.

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 27


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Exemple : Ajouter des données depuis un formulaire

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 28


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Formulaire de base

<html>
<head>
<title>Todo App</title>
</head>
<body>
<form method="post" action="/todos/create">
<input type="text" name="description" />
<input type="submit" value="Create" />
</form>
<ul>
{% for d in data %}
<li>{{ d.description }}</li>
{% endfor %}
</ul>
</body>
</html>

Il faut modifier app.py de façon à pouvoir enregistrer les données dans la base de données :
Le résultat final doit ressembler à ceci :

K- Gestion des exceptions


Implémentation try… except… finally

import sys

try:
todo = Todo(description=description)
db.session.add(todo)
db.session.commit()

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 29


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

except:
db.session.rollback()
error=True
print(sys.exc_info())
finally:
db.session.close()

L- Implémentation dans l’application


Code (avec corrections)
from flask import Flask, render_template, abort

# ...

@app.route('/todos/create', method=['POST'])
def create_todo():
error = False
body = {}
try:
description = request.get_json()['description']
todo = Todo(description=description)
db.session.add(todo)
db.session.commit()
body['description'] = todo.description
except:
error = True
db.session.rollback()
print(sys.exc_info())
finally:
db.session.close()
if error:
abort (400)
else:
return jsonify(body)

S'entraîner
Implémentez ce modèle try-except-finally dans notre gestionnaire de route d'élément de création de
tâches.

Code de démarrage
app.py
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://udacitystudios@localhost:5432/todoa
pp'
db = SQLAlchemy(app)

class Todo(db.Model):
__tablename__ = 'todos'
id = db.Column(db.Integer, primary_key=True)

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 30


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

description = db.Column(db.String(), nullable=False)

def __repr__(self):
return f'<Todo {self.id} {self.description}>'

db.create_all()

@app.route('/todos/create', method=['POST'])
def create_todo():
description = request.get_json()['description']
todo = Todo(description=description)
db.session.add(todo)
db.session.commit()
return jsonify({
'description': todo.description
})

@app.route('/')
def index():
return render_template('index.html', data=Todo.query.all())
modèles/index.html
<html>
<head>
<title>Todo App</title>
<style>
#error {
display: none;
}
</style>
</head>
<body>
<div id="error" class="hidden">Something went wrong!</div>
<form id="form" method="post" action="/todos/create">
<input type="text" id="description" name="description" />
<input type="submit" value="Create" />
</form>
<ul id="todos">
{% for d in data %}
<li>{{ d.description }}</li>
{% endfor %}
</ul>
<script>
const descInput = document.getElementById('description');
document.getElementById('form').onsubmit = function(e) {
e.preventDefault();
const desc = descInput.value;
descInput.value = '';
fetch('/todos/create', {
method: 'POST',
body: JSON.stringify({
'description': desc,
}),
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 31


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

.then(jsonResponse => {
console.log('response', jsonResponse);
li = document.createElement('li');
li.innerText = desc;
document.getElementById('todos').appendChild(li);
document.getElementById('error').className = 'hidden';
})
.catch(function() {
document.getElementById('error').className = '';
})
}
</script>
</body>
</html>

M- Les migrations dans Python Flask


Les migrations traitent de la façon dont nous gérons les modifications apportées à notre schéma de don-
nées, au fil du temps.

Les erreurs à notre schéma de base de données sont très coûteuses. L'ensemble de l'application peut tom-
ber en panne, nous voulons donc annuler rapidement les modifications, et tester les modifications avant
de les faire.

Une migration est un fichier qui garde une trace des modifications apportées à notre schéma de base de
données (structure de notre base de données).
Offre un contrôle de version sur notre schéma.

Scripts de ligne de commande de migration


Il y a généralement 3 scripts nécessaires, pour
1. migrate : création d'un modèle de script de migration à remplir ; génération d'un fichier de
migration en fonction des modifications à apporter
2. upgrade : application des migrations qui n'avaient pas encore été appliquées ("upgrading"
de notre base de données)
3. downgrade : roll back des migrations appliquées qui posaient problème ("downgrading" de
notre base de données)

Bibliothèque de migration pour Flask + SQLAlchemy


1. Flask-Migrate est notre bibliothèque pour migrer les modifications à l'aide de
SQLAlchemy. Il utilise une bibliothèque appelée Alembic sous le capot.
2. Flask-Migrate & Flask-Script
3. Flask-Migrate (flask_migrate) est notre gestionnaire de migration pour migrer les modifica-
tions de base de données basées sur SQLALchemy
4. Flask-Script (flask_script) nous permet d'exécuter les scripts de migration que nous avons
définis, à partir du terminal

Étapes pour lancer les migrations


1. Initialiser la structure du référentiel de migration pour stocker les migrations
2. Créer un script de migration (à l'aide de Flask-Migrate)
3. (Manuellement) Exécutez le script de migration (à l'aide de Flask-Script).
Lien utile : https://flask-migrate.readthedocs.io/en/latest/

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 32


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 33


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Installation de Flask-Migrate

pip3 install Flask-Migrate


flask db init

Exemple de migration de données

Voici un exemple d'application qui gère les migrations de bases de données via Flask-Migrate :

from flask import Flask

from flask_sqlalchemy import SQLAlchemy

from flask_migrate import Migrate

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'

db = SQLAlchemy(app)

migrate = Migrate(app, db)

class User(db.Model):

id = db.Column(db.Integer, primary_key=True)

name = db.Column(db.String(128))

Avec l'application ci-dessus, vous pouvez créer un référentiel de migration avec la commande sui-
vante :

$ flask db init

Cela ajoutera un dossier de migrations à votre application. Le contenu de ce dossier doit être ajouté
au contrôle de version avec vos autres fichiers source.

Vous pouvez ensuite générer une migration initiale :

$ flask db migrate -m "Initial migration."

Le script de migration doit être examiné et modifié, car Alembic ne détecte actuellement pas toutes
les modifications que vous apportez à vos modèles. En particulier, Alembic est actuellement inca-
pable de détecter les changements de nom de table, les changements de nom de colonne ou les con-
traintes nommées anonymement. Un résumé détaillé des limitations peut être trouvé dans la docu-
mentation de génération automatique d'Alembic . Une fois finalisé, le script de migration doit égale-
ment être ajouté au contrôle de version.

Ensuite, vous pouvez appliquer la migration à la base de données :

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 34


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

$ flask db upgrade

Ensuite, chaque fois que les modèles de base de données changent, répétez les commandes migrate
et upgrade.

Pour synchroniser la base de données dans un autre système, actualisez simplement le dossier migra-
tions à partir du contrôle de source et exécutez la commande upgrade.

Pour voir toutes les commandes qui sont disponibles cette exécution commande:

$ flask db --help

Notez que le script d'application doit être défini dans la FLASK_APP variable d'environnement pour
que toutes les commandes ci-dessus fonctionnent, comme requis par le flaskscript de ligne de com-
mande.

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 35


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Partie 2 :

Développement des API


avec Python Flask

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 36


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

A- Qu’est-ce qu’une API ? (Roy Fielding)


Une API permet de rendre disponibles les données ou les fonctionnalités d’une application existante
afin que d’autres applications les utilisent. Voici qui devrait rendre la notion d’interface de pro-
grammation applicative plus claire 😊

Utiliser une API permet donc d’utiliser un programme existant plutôt que de le re-développer. C’est
donc un grand gain de temps à la clé.

Ce que peut faire une api concrètement


La première chose que fait une API, c’est qu’elle expose, autrement dit, elle rend disponibles des
fonctionnalités ou des données. Pour les utiliser, la plupart des API requièrent une clé (API key),
voire parfois deux. Cette clé permet à l’API de vous identifier comme étant un utilisateur ayant les
droits nécessaires pour se servir de l’API.

Exemples d’API :

- Google Map API

- PayPal

- Strike API

B- Architecture client-serveur avec une API

NB : Les protocoles utilisés par l’API pour envoyer des requêtes et recevoir les réponses sont le
TCP et HTTP.

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 37


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

C- RESTful
1. La particularité de cette architecture est que la partie serveur et la partie client communiquent
sans que le client ne connaisse la structure et le contenu des informations stockées sur le ser-
veur.

2. Une API est RESTful quand elle respecte le principe d'architecture REST. Ce principe d'ar-
chitecture s'applique aux services Web. La particularité principale de cette architecture est que
la partie serveur (l'API) et la partie client communiquent sans que le client ne connaisse la
structure et le contenu des informations stockées sur le serveur. La seule chose que les deux
parties de l'application connaissent est le média qu'elles utilisent pour communiquer.
3. Les applications REST s'appuient sur les verbes fournis par le protocole HTTP. Ce sont des
mots-clés qui définissent l'action que l'on souhaite effectuer sur une ressource. Les deux
principaux sont GET et POST mais il existe également PUT, DELETE et PATCH. Le média
peut être par exemple un fichier JSON ou XML.
4. Pour commencer la communication, le client va appeler l'URL racine de l'API, /. Requête :
GET /

Accept: application/json

D- Composant d’une requête http


1- Structure d’une requête http

2- Liste des méthodes

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 38


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

3- Liste des réponses http (Status Code)

4- Les Status code les plus connus :

200 : OK
201 : Created
304 : Not Modified
400 : Bad Request
401 : Unauthorized
404 : Not Found
405 : Method Not Allowed
500 : Internal Server Error

E- Créer l'application Flask de base


Configurons l'application Flask de base dans le fichier /flaskr/__init__.py .
# Import your dependencies
from flask import Flask, jsonify
# Define the create_app function
def create_app(test_config=None):
# Create and configure the app
# Include the first parameter: Here, __name__is the name of the current Python module.
app = Flask(__name__)

# Return the app instance


return app

Ensuite, j'inclurai comment configurer l'application pour gérer une configuration spécialisée.

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 39


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

F- Premier point de terminaison avec JSON


Avant de renvoyer l'application, utilisez le décorateur @app.route pour créer un point de terminaison
vers le chemin / et définir une fonction pour gérer cette route.

@app.route('/')
def hello_world():
return 'Hello, World!'
return app

Au lieu de renvoyer du texte, utilisez jsonify pour envoyer un objet contenant le message
return jsonify({'message':'Hello, World!'})
Pour Windows cmd, utilisez set au lieu d'export :

> set FLASK_APP=flaskr


> set FLASK_ENV=development
> flask run

G- Comment interroger votre API à l’aide


du cmd
1- Commande curl
Pour tester un GET:
curl -i http://localhost/silex/api/v1/contact/2

Pour tester un POST:¶


curl -i -H "Content-Type: application/json" -X POST
-d '{"NOM":"Dalton", "PRENOM":"joe", "NAISSANCE":"2000-08-15", "VILLE":"Orleans"}'
http://localhost/silex/api/contact

Pour plus d’information consulter : https://www.univ-orleans.fr/iut-


orleans/informatique/intra/tuto/php/rest-api-tests-curl.html

2- Utilisation de Postman
Postman est une application permettant d’envoyer des requêtes vers les API. Pour l’installer,
télécharger sur le lien suivant : https://www.postman.com/downloads/ . Actuellement, il existe une
version à intégrer avec le navigateur chrome.

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 40


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

H- Cross Origin Policy


Le « Cross-origin resource sharing » (CORS) ou « partage des ressources entre origines multiples »
(en français, moins usité) est un mécanisme qui consiste à ajouter des en-têtes HTTP afin de permettre
à un agent utilisateur d'accéder à des ressources d'un serveur situé sur une autre origine que le site
courant. Un agent utilisateur réalise une requête HTTP multi-origine (cross-origin) lorsqu'il demande
une ressource provenant d'un domaine, d'un protocole ou d'un port différent de ceux utilisés pour la
page courante.

Prenons un exemple de requête multi-origine : une page HTML est servie depuis http://domaine-
a.com contient un élément <img> src ciblant http://domaine-b.com/image.jpg. Aujourd'hui, de nom-
breuses pages web chargent leurs ressources (feuilles CSS, images, scripts) à partir de domaines sé-
parés (par exemple des CDN (Content Delivery Network en anglais ou « Réseau de diffusion de con-
tenu »).

Pour mieux comprendre : https://developer.mozilla.org/fr/docs/Web/HTTP/CORS

- Implémentation du CORS Origin dans notre API

5. Le code complet est visible ci-dessous :


from flask import Flask, jsonify
from models import setup_db, Plant
from flask_cors import CORS, cross_origin

def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
setup_db(app)
#CORS(app, resources={r"*/api/*" : {origins: '*'}})
CORS(app)

@app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Headers', 'Content-Type, Autho
rization')

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 41


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

response.headers.add('Access-Control-Allow-Headers', 'GET, POST, PATCH, D


ELETE, OPTION')
return response

#@cross_origin
@app.route('/')
def hello_world():
return jsonify({'message':'HELLO, WORLD!'})
return app

I- Cas pratique
- Regarder l’API Plants sur https://github.com/badiou/plants_api.git

- Lire la documentation de l’API sur le site

- Montrer le CORS

- Montrer le modèle

- Montrer les modèles

- Montrer les tests unitaires

J-Tests unitaires : TDD


Test-Driven Development (TDD), ou Développements Pilotés par les Tests en français, est une mé-
thode de développement de logiciel, qui consiste à concevoir un logiciel par petits pas, de façon ité-
rative et incrémentale, en écrivant chaque test avant d'écrire le code source et en remaniant le code
continuellement.

import unittest
import json
import os
from flask_sqlalchemy import SQLAlchemy
from flaskr import create_app
from models import setup_db, Plant

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 42


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

class PlanttestCase(unittest.TestCase):
"""This class represents the plant test case"""

def setUp(self):
"""Define test variables and initialize app."""
self.app = create_app()
self.client = self.app.test_client
self.database_name = "plants_database_test"
self.database_path = "postgresql://{}:{}@{}/{}".format(
'postgres', 'badiou', 'localhost:5432', self.database_name)

setup_db(self.app, self.database_path)
with self.app.app_context():
self.db = SQLAlchemy()
self.db.init_app(self.app)
# create all tables
self.db.create_all()
self.new_plant = {
'name': 'Champignon vénimeux',
'is_poisonous': True,
'scientific_name': 'Champi - Kilo Adansonia DIGITATA',
'primary_color': 'Green',
'state': 'TOGO'
}

def tearDown(self):
"""Executed after reach test"""
pass

"""
TODO
Write at least one test for each test for successful operation and for expected
errors.
"""

def test_get_all_plants(self):
res = self.client().get('/plants')

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 43


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

# ici on récupère les données provenant de la Response


data = json.loads(res.data)
self.assertEqual(res.status_code, 200)
self.assertEqual(data['success'], True)
self.assertTrue(data['plants'])
self.assertTrue(len(data['totals_plants']))

def test_paginate_plants(self):
res = self.client().get('/plants')
data = json.loads(res.data)
self.assertEqual(res.status_code, 200)
self.assertTrue(data['current_plants'])
self.assertTrue(data['current_plants'])

def test_delete_plant(self):
res=self.client().delete('/plants/101')
data=json.loads(res.data)
plant=Plant.query.filter(Plant.id == 101).one_or_none()
self.assertEqual(res.status_code, 200)
self.assertEqual(data['success'], True)
self.assertEqual(data['deleted'], 101)
self.assertTrue(data['plants'], True)
self.assertTrue(data['totals_plants'])

def test_plant_which_does_not_exist(self):
res=self.client().delete('/plants/1000')
data=json.loads(res.data)
plant=Plant.query.filter(Plant.id == 1000).one_or_none()
self.assertEqual(res.status_code, 422)
self.assertEqual(data['success'], False)
self.assertEqual(data['message'], 'unprocessable')

def test_create_new_plant(self):
res=self.client().post('/plants', json = self.new_plant)
data=json.loads(res.data)
self.assertEqual(res.status_code, 200)
self.assertTrue(data['success'], True)
self.assertTrue(data['created'])
self.assertTrue(data['plants'])

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 44


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

self.assertEqual(len(data['plants']))

def test_404_requesting_beyond_the_value_page(self):
res=self.client().get('/plants?page=1000')
data=json.loads(res.data)
self.assertEqual(res.status_code, 404)
self.assertEqual(data['success'], False)
self.assertEqual(data['message'], 'Not found')

def test_404_requesting_select_on_plant(self):
res=self.client().get('/plants/1000')
data=json.loads(res.data)
self.assertEqual(res.status_code, 404)
self.assertEqual(data['success'], False)
self.assertEqual(data['message'], 'Not found')

def test_update_plant_primary_color(self):
res=self.client().patch('/plants/102',json={'primary_color':'Gray'})
data=json.loads(res.data)
plant=Plant.query.filter(Plant.id == 102).one_or_none()
self.assertEqual(res.status_code,200)
self.assertEqual(data['success'],True)
self.assertEqual(plant.format()['primary_color'],'Gray')

def test_get_plant_search_with_result(self):
res=self.client().post('/plants',json={'search':'Baobab'})
self.assertEqual(res.status_code,200)
self.assertEqual(data['success'],True)
self.assertEqual(len(data['total_plants']))
self.assertEqual(len(data['plants']),4)

# # Make the tests conveniently executable


if __name__ == "__main__":
unittest.main()

K- Documentation de votre API : Qu’est-ce


que doit contenir votre documentation ?

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 45


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Consulter ce lien comme exemple de documentation de l’API : https://github.com/ba-


diou/plants_api#readme

L- Devoir à faire par chaque étudiant


Chaque étudiant doit choisir un domaine de son choix avec une base de données de 2 tables au mi-
nimum.
1- Concevoir la base de données en utilisant les migrations
2- Développer l’API
3- Faire les tests unitaires
4- Mettre en place la documentation de l’API
5- Déposer son API sur Github.
6- Deployer l’API sur Heroku (Plateforme Cloud)
7- Faire ensuite les tests en changeant le nouveau {{host}}

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 46


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Partie 3 :

Sécurisation des API


Cette partie partie sera abordée oralement avec les étudiants :

https://auth0.com/blog/using-python-flask-and-angular-to-build-modern-web-apps-part-2/

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 47


OURO-BANG’NA Badiou, Full-Stack Developer
COURS DE DEVELOPPEMENT PYTHON AVEC LE FRAMEWORK FLASK

Partie 4 :

Déploiement de l’API
Cette partie est résumé dans la vidéo ci-dessous. La vidéo doit être suivie par l’étudiant. L’ensei-
gnant fait une brève présentation du contenu de la vidéo
https://www.youtube.com/watch?v=23sp3cj5Pnc&t=33s

OURO-BANG’NA BADIOU, FULL-STACK DEVELOPER 48

Vous aimerez peut-être aussi