• 8 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 01/02/2019

Ajoutez une nouvelle table dans la base de données

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

 

Dans le chapitre précédent vous avez appris à lancer un serveur avec Flask et à configurer un projet. Avant de voir comment afficher la page index.html, créons une base de données dans laquelle nous garderons précieusement les différentes descriptions.

Qu'est-ce qu'une base de données ? Et pourquoi ne pas commencer par l'affichage de la page index.html ?

Ce sont de bonnes questions ! Afin de proposer à l'utilisateur une description de sa personnalité, nous devons être en mesure de chercher des descriptions. Or, comment trouver une information qui n'est enregistrée nulle part ? Il est donc préférable de commencer par la création de la base de données et des différents éléments qu'elle contiendra.

Mais je reviens à votre première question.

Qu'est-ce qu'une base de données ?

Une base de données est très similaire à un grand tableau Excel contenant plusieurs feuilles. Nous pouvons chercher des données, en créer, en modifier ou en supprimer. Les données sont organisées en tables, lignes et colonnes.

Alors, pourquoi ne pas directement travailler sur Excel ?

Excel n'a pas été conçu pour une application web : il s'agit d'un outil de gestion visuel dont le principal intérêt est l'interface graphique. Nous pouvons dire que les bases de données sont l'Excel des applications web ! ;) 

Types de bases de données

Il existe plusieurs types de bases de données. Plus précisément, ce sont plutôt des Systèmes de Gestion de Bases de Données (SGBD) répartis en deux grandes familles :

  • SGBD relationnels : les données sont représentées dans des tableaux pouvant être liés les uns avec les autres,

  • SGBD NoSQL : les données ne sont pas structurées en tableaux mais autrement : graphe, clé/valeur...

Dans ce cours nous utiliserons SQLite, un SGBD relationnel, mais il en existe d'autres : MySQL, PostgreSQL, Oracle Database... J'ai choisi SQLite car il est libre et facile à apprendre.

Structure d'une base dans un SGBD relationnel

La base de données contient des tables qui elles-mêmes contiennent des champs et des items. Si nous gardons notre comparaison avec Excel, la base de données serait le fichier Excel, une table serait une feuille et un champ le nom d'une colonne.

Avant de créer une table, il est important d'en connaître la structure. J'utilise l'outil SQL Vizualizer, gratuit et en ligne, pour visualiser la structure d'un projet. Voici à quoi ressemblera la base de données de notre projet :

Interroger une base

Pour interagir avec un SGBD relationnel nous utilisons un langage appelé SQL (Structured Query Language). Ce langage permet d'ajouter, modifier ou supprimer des données mais aussi d'interroger la base selon certains critères et faire des recoupements d'information en suivant les relations entre les tables.

Une requête SQL peut ressembler à ceci :

SELECT * FROM content

Ceci affichera tous les items de la table content. Mais ne vous inquiétez pas : vous n'aurez pas besoin d'apprendre un nouveau langage. Nous allons utiliser Flask pour l'interroger à notre place ! :)

Utiliser SQLite avec Flask

Avant d'interroger une base SQLite avec Flask, vous devez installer le logiciel. Allez sur la page de téléchargement et cliquez sur le lien correspondant à votre système d'exploitation. Puis suivez les instructions.

Créez un nouveau document à la racine de votre projet : app.db. Il s'agira de notre base de données.

C'est tout ! Vous n'avez plus rien à faire. Revenons maintenant à Flask et voyons comment interroger la base de données. 

Utiliser un ORM

Je vous ai dit précédemment que vous n'aviez pas besoin d'apprendre SQL car Flask intégrait un outil qui le faisait pour vous. J'ai un peu enjolivé la réalité, j'espère que vous ne m'en voudrez pas trop !

Par défaut Flask ne gère pas les bases de données. Vous devez installer une extension, SQLAlchemy, qui fera le pont entre la base de données et votre application.

Plus spécifiquement, vous écrirez des requêtes en Python et SQLAlchemy les traduira en SQL. Puis elle vous renverra les résultats de la requête sous la forme d'objets Python avec lesquels vous pourrez interagir.

Un peu comme un traducteur automatique !

C'est ce que nous appelons un ORM (Object Relational Mapping, ou Mapping objet-relationnel en français).

Alors, comment utiliser SQLAlchemy ? Commencez par l'installer en utilisant pip :

$ pip install flask_sqlalchemy

Puis modifiez le fichier config.py en ajoutant ces lignes :

config.py

import os

...

basedir = os.path.abspath(os.path.dirname(__file__))
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db')

Cela permettra à l'ORM de savoir où se situe notre base de données pour pouvoir l'interroger.

Avant de connecter l'application à la base de données, créons un premier modèle. 

Définir un modèle

Un modèle représente la donnée qui est stockée en base. Il indique à l'ORM la structure que vous souhaitez pour chaque table ainsi que les associations.

Vous devez également indiquer le type de chaque champ : est-ce un entier, une chaîne de caractères, un booléen ?

Dans ce cours nous n'aurons besoin que d'une table (Content) qui contient trois champs :

  • id : identifiant unique de l'item. Il s'agit d'un entier et il est très fortement conseillé de l'indiquer pour tout nouvel item que vous créez.

  • description : la description que l'utilisateur verra. Il s'agit d'une chaîne de 200 caractères maximum.

  • gender : le genre de la description (féminin, masculin ou non renseigné). Étant donné qu'il n'y a que trois choix possibles, nous enregistrons l'information sous la forme d'un entier. 

Créez un nouveau fichier models.py dans le dossier fbapp. Il contiendra toutes les tables que vous souhaitez créer ainsi que leur structure.

models.py

from flask_sqlalchemy import SQLAlchemy

from .views import app

# Create database connection object
db = SQLAlchemy(app)

class Content(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    description = db.Column(db.String(200), nullable=False)
    gender = db.Column(db.Integer(), nullable=False)

    def __init__(self, description, gender):
        self.description = description
        self.gender = gender

db.create_all()

Connecter la base

Maintenant, nous devons indiquer à Flask que nous utilisons une base de données. Modifions le fichier __init__.py :

fbapp/__init__.py

from flask import Flask

from .views import app
from . import models

# Connect sqlalchemy to app
models.db.init_app(app)

Si vous lancez le serveur, rien ne se produit. En apparence ! Afin d'être sûrs que la table Content a bien été créée, "entrons" dans le programme afin d'interagir directement avec la base de données. 

Découvrir la console Flask

Nous pourrions utiliser PDB, le débogueur de Python, mais je vais plutôt vous montrer comment lancer la console interactive de Flask.

Dans votre console, exécutez la commande suivante :

Mac OS ou Linux

$ FLASK_APP=run.py flask shell

Windows

$ set FLASK_APP=run.py
$ flask shell

 

Une console s'ouvre :

Python 3.6.1 (default, Mar 23 2017, 16:49:06)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
App: fbapp.views
Instance: /Users/celinems/sites/oc/exercices_exemples/flask_example/instance
>>>  

Python attend vos instructions. Vous avez accès à quelques objets, dont app :

>>> app
<Flask 'fbapp.views'>
>>> app.config
<Config {'DEBUG': False, 'TESTING': False, ...}

Utilisons cette console pour interagir avec la base. Importez les modèles et commençons :

>>> from fbapp.models import db, Content
>>> db.session.add(Content("What's your favorite scary movie?", 0))
>>> db.session.commit()
>>> Content.query.all()
>>> [<fbapp.models.Content object at 0x1040518d0>]

Je vais vous expliquer ce qui s'est passé !

  • db.session.add() : Cette méthode permet d'ajouter un item à la base. En paramètres, vous passez l'instance de l'objet que vous voulez créer.

  • db.session.commit() : Chaque création est ajoutée dans une session. Lorsque vous avez terminé d'ajouter des éléments, vous devez indiquer à SQLAlchemy de faire les requêtes dans la base pour finaliser l'opération.

  • Content.query.all() : Cette méthode renvoie tous les items de la table Content. En réponse, nous voyons que nous avons bien un item. 

Les sessions de SQLAlchemy permettent de gérer les transactions SQL, autrement dit un ensemble de requêtes. Si l'une d'elles échoue, l'ensemble de la transaction est annulée et aucune requête n'est communiquée à la base.

Il s'agit d'un système très utile pour gérer des séquences d'opérations dépendantes les unes des autres. Par exemple, si nous réalisons les deux opérations suivantes :

  1. Création d'un utilisateur

  2. Création des propriétés de cet utilisateur dans une autre table (son nom, son mot de passe...)

Imaginons que la deuxième requête échoue. Nous nous retrouvons alors avec un utilisateur sans permission et notre base est dans un état corrompu. Il aurait mieux fallu ne pas créer l'utilisateur du tout !

Interagir avec la base via SQLAlchemy

Nous avons vu comment ajouter des items en utilisant la méthode add(). Voyons maintenant comment modifier un item ou le supprimer. Utile, n'est-ce pas ?

Avant de pouvoir modifier un item, il faut le retrouver ! Comment trouver un item ? La méthode la plus simple est de chercher via son id, identifiant unique.

>>> content = Content.query.get(1)
<fbapp.models.Content object at 0x1061d98d0>
>>> content.description
"What's your favorite scary movie?"
>>> content.description = "Il s'appelle Juste Leblanc."
>>> db.session.commit()

Pour supprimer un élément, utilisez delete(element) :

>>> content = Content.query.get(1)
<fbapp.models.Content object at 0x1061d98d0>
>>> db.session.delete(content)
>>> db.session.commit()

Peupler la table de données pré-existantes

Nous touchons presque au but !

La dernière étape, si vous l'acceptez, est d'ajouter des descriptions à la base une seule fois. En effet, le script models.py est lancé à chaque démarrage du serveur. Cela veut dire que le script tentera de créer la table une seconde fois à chaque nouveau démarrage !

Comment faire ?

Je vous propose de lancer la création en ligne de commande et non pas dans le script. Nous pourrions ainsi écrire FLASK_APP=run.py flask init_db.

Voici comment faire !

fbapp/__init__.py

...
@app.cli.command()
def init_db():
    models.init_db()

Puis nous ajoutons la méthode dansmodels.py:

models.py

import logging as lg

...

def init_db():
    db.drop_all()
    db.create_all()
    db.session.add(Content("THIS IS SPARTAAAAAAA!!!", 1))
    db.session.add(Content("What's your favorite scary movie?", 0))
    db.session.commit()
    lg.warning('Database initialized!')

À présent, lançons l'initialisation :

$ FLASK_APP=run.py flask init_db
WARNING:root:Database initialized!

Ça a fonctionné !

Code du chapitre

Ce chapitre occulte de nombreux aspects des bases de données. Afin d'aller plus loin, je vous conseille le cours Faites une base de données avec UML.

Retrouvez le code de ce chapitre ici à cette adresse.

Exemple de certificat de réussite
Exemple de certificat de réussite