Lorsque l'on développe une application Flask, le choix de la gestion des données est crucial.
Pour transformer vos objets Python en tables de base de données sans écrire une seule ligne de SQL, le duo Flask-SQLAlchemy et Flask-Migrate est l'outil standard de l'écosystème.
1. Flask-SQLAlchemy : La puissance de l'ORM
Flask-SQLAlchemy simplifie l'utilisation d'SQLAlchemy. Un ORM (Object Relational Mapper) permet d'interagir avec votre base de données en manipulant des classes Python.
Pourquoi l'adopter ?
- Abstraction : Plus besoin de jongler avec des requêtes SQL complexes.
- Flexibilité : Changez de moteur de base de données (SQLite vers PostgreSQL) avec une simple ligne de configuration.
- Intégration : Conçu spécifiquement pour s'intégrer dans le cycle de vie d'une application Flask.
2. Flask-SQLAlchemy et Flask-Migrate : Explication et Utilisation
Lorsque l'on développe une application Flask qui nécessite une base de données, il est important de choisir une bibliothèque pour interagir avec cette base et pour gérer les évolutions du schéma.
Flask-SQLAlchemy et Flask-Migrate sont deux extensions essentielles pour cela.
Avec Flask, la gestion des migrations de base de données se fait généralement avec Flask-Migrate, une extension basée sur Alembic.
Elle permet de suivre et d'appliquer les modifications du schéma de la base de données sans perdre les données existantes.
3. Flask-SQLAlchemy : Gestion de la Base de Données
📌 Qu'est-ce que Flask-SQLAlchemy ?
Flask-SQLAlchemy est une extension qui simplifie l'utilisation d'
SQLAlchemy dans une application Flask.
SQLAlchemy est un ORM (Object Relational Mapper) puissant qui permet d'interagir avec une base de données en utilisant des objets Python au lieu d'écrire des requêtes SQL brutes.
🚀 Pourquoi utiliser Flask-SQLAlchemy ?
- Facilite la gestion des bases de données en Flask.
- Permet d’écrire des requêtes SQL de manière plus intuitive en Python.
- Prend en charge plusieurs types de bases de données (SQLite, PostgreSQL, MySQL, etc.).
- Fournit un système de migration facile à utiliser avec Flask-Migrate.
🔧 Exemple de configuration de Flask-SQLAlchemy
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db' # Connexion à SQLite
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app) # Création de l'instance SQLAlchemy
# Définition d'un modèle pour une table "users"
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
# Création de la base de données (uniquement lors de la première exécution)
with app.app_context():
db.create_all()
4. Flask-Migrate : Gestion des Migrations
📌 Qu'est-ce que Flask-Migrate ?
Flask-Migrate est une extension qui permet de gérer les migrations de base de données en SQLAlchemy avec Alembic.
Une migration permet d'apporter des modifications à la structure de la base de données (ajout de colonnes, suppression de tables, modification de types de données, etc.) sans perdre les données existantes.
🚀 Pourquoi utiliser Flask-Migrate ?
- Permet d'appliquer des changements sur la base de données de manière progressive.
- Facilite la gestion des versions du schéma de base de données.
- Évite d’avoir à supprimer et recréer la base de données à chaque modification.
---
📌 Étapes pour utiliser `flask db migrate`
Voici comment fonctionne la migration avec Flask :
- Installation de Flask-Migrate
Si ce n’est pas déjà fait, installe Flask-Migrate et SQLAlchemy :
```bash
pip install flask-migrate flask-sqlalchemy
```
- Initialisation du projet
Dans ton application Flask, tu dois avoir SQLAlchemy configuré :
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db' # Ou autre SGBD (PostgreSQL, MySQL, etc.)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
migrate = Migrate(app, db) # Intégration avec Flask-Migrate
# Définition d’un modèle
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
completed = db.Column(db.Boolean, default=False)
if __name__ == '__main__':
app.run(debug=True)
- Initialisation de Flask-Migrate
Crée un dossier de migration dans ton projet :
👉 Cela génère un dossier `migrations/` contenant la configuration de Alembic.
- Création d'une migration
Si tu ajoutes un nouveau modèle ou modifies un champ, Flask-Migrate va générer une migration :
flask db migrate -m "Ajout du modèle Task"
👉 Cette commande crée un fichier dans `migrations/versions/` qui contient les instructions de modification du schéma.
- Application de la migration
Une fois la migration créée, applique-la à la base de données :
👉 Cela exécute le script de migration et met à jour la base.
- Gérer les modifications du modèle
Si tu modifies un modèle (ex: ajouter une colonne `due_date` à `Task`) :
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
completed = db.Column(db.Boolean, default=False)
due_date = db.Column(db.DateTime) # Nouvelle colonne
Exécute les migrations :
flask db migrate -m "Ajout de due_date à Task"
flask db upgrade
Annuler la dernière migration (si besoin) :
🛠 Commandes utiles
5. Résumé des commandes
| Commande |
Description |
| flask db init |
Initialise le dossier `migrations |
| flask db migrate -m "Message" |
Génère un fichier de migration basé sur les modifications du modèle |
| flask db upgrade |
Applique la migration à la base de données |
| flask db downgrade |
Annule la dernière migration |
| flask db history |
Affiche l'historique des migrations |
| flask db current |
Montre la version actuelle appliquée |
6. Exemples d'utilisation
Ajout d’une colonne dans un modèle existant
Si l'on souhaite ajouter une nouvelle colonne `age` au modèle `User`, il suffit de :
- Modifier le modèle Python :
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
age = db.Column(db.Integer, nullable=True) # Nouvelle colonne
- Générer une nouvelle migration :
flask db migrate -m "Ajout de la colonne age à User"
- Appliquer la migration :
6. Résumé
| Outil |
Rôle |
| Flask-SQLAlchemy |
Gère la connexion et l'interaction avec la base de données via un ORM |
| Flask-Migrate |
Permet d'appliquer des modifications au schéma de la base sans perdre de données |
7. Modéliser les relations entre données
La puissance d'une base relationnelle réside dans les liens entre les tables. Voici comment les implémenter proprement :
Relation One-to-Many (1 → N)
C'est la relation la plus commune (ex: Un utlisateur possède plusieurs articles).
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
articles = db.relationship('Article', backref='author', lazy=True)
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
- db.relationship() est utilisé côté "parent" (ici `User`).
- db.ForeignKey()` est utilisé côté "enfant" (ici `Article`).
Relation One-to-One (1 → 1)
Exemple : Un utilisateur a un seul profil.
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
profile = db.relationship('Profile', backref='user', uselist=False)
class Profile(db.Model):
id = db.Column(db.Integer, primary_key=True)
bio = db.Column(db.String(200))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
- uselist=False rend la relation unitaire (1:1).
- Même principe que 1\:N sinon.
Relation Many-to-Many (N ↔ N)
Exemple : Un étudiant peut suivre plusieurs **cours**, et un cours peut avoir plusieurs étudiants.
Pour les cas complexes (ex: Étudiants et Cours), une table d'association est requise.
association_table = db.Table('association',
db.Column('student_id', db.Integer, db.ForeignKey('student.id')),
db.Column('course_id', db.Integer, db.ForeignKey('course.id'))
)
class Student(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
courses = db.relationship('Course', secondary=association_table, backref='students')
class Course(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100))
- Une table d'association (`association_table`) est nécessaire.
- Utilisation de `secondary=` dans `db.relationship()` pour établir le lien.
Récapitulatif rapide :
| Relation |
Côté A |
Côté B |
| One-to-Many |
db.relationship() |
db.ForeignKey() |
| One-to-One |
db.relationship(uselist=False) |
db.ForeignKey() |
| Many-to-Many |
db.relationship(secondary=...) |
Table d'association avec `db.Table()` |
Grâce à **Flask-SQLAlchemy**, on manipule la base de données en Python, et avec Flask-Migrate, on gère les modifications de manière souple et sécurisée. 🚀