Tu as déjà croisé un script Python qui trimballe son SQL dans des chaînes de caractères ? Un f"SELECT * FROM users WHERE name = '{nom}'" qui fonctionne très bien, jusqu'au jour où un nom contient une apostrophe — ou pire, jusqu'au jour où quelqu'un y glisse une injection. SQLAlchemy règle le problème à la racine. Au lieu d'écrire du SQL à la main, tu décris tes tables avec de simples classes Python, et l'ORM se charge de traduire tes intentions en SQL propre, paramétré et sécurisé.
Résultat : ton code est lisible, tes données sont typées, et tu passes de SQLite à PostgreSQL en changeant une seule ligne. On y va.
Prérequis
Rien de plus que Python 3 et la bibliothèque sqlalchemy. SQLite est intégré à Python, donc tu n'as même pas besoin d'installer un serveur de base de données pour suivre ce tutoriel.
pip install sqlalchemyÉtape 1 — Le moteur, ton point d'entrée
Tout commence par un Engine, l'objet qui gère la connexion à ta base. Pour SQLite, c'est une seule ligne. On laisse echo=False pour ne pas noyer la console, mais mets-le à True une fois : tu verras le SQL exact que SQLAlchemy génère derrière ton dos.
from sqlalchemy import create_engine
# SQLite stocke tout dans un fichier local : tutorial.db
engine = create_engine("sqlite:///tutorial.db", echo=False)Étape 2 — Décris tes tables avec des classes
Ici, pas de CREATE TABLE à écrire : tu déclares une classe Python par table, et chaque attribut devient une colonne. Le type de chaque colonne est explicite, ce qui te protège des surprises au moment de l'insertion.
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy import String, Integer, Float
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = "articles"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
titre: Mapped[str] = mapped_column(String(200))
mots: Mapped[int] = mapped_column(Integer)
note: Mapped[float] = mapped_column(Float)Étape 3 — Crée les tables en une ligne
Base.metadata connaît toutes les classes que tu as déclarées. create_all() génère les tables manquantes. Pour un vrai projet en équipe, tu préféreras Alembic afin de versionner ton schéma, mais pour démarrer, c'est largement suffisant.
Base.metadata.create_all(engine)Étape 4 — Insère des données sans SQL
La session est ton intermédiaire avec la base. Tu y ajoutes des objets Python, et commit() écrit tout en une seule transaction. Le typage t'empêche d'insérer un texte là où la colonne attend un entier.
from sqlalchemy.orm import Session
with Session(engine) as session:
session.add_all([
Article(titre="SQLAlchemy : le tutoriel", mots=1024, note=4.7),
Article(titre="Pourquoi j'ai arrêté le SQL brut", mots=810, note=4.2),
Article(titre="Les bases de données, sans douleur", mots=640, note=3.9),
])
session.commit()Étape 5 — Interroge avec du Python, pas du SQL
La requête se lit comme du code : tu filtres, tu tries, tu limites. Pas de concaténation de chaînes, donc pas d'injection possible. Le résultat est une liste d'objets Article, avec accès direct aux attributs. La méthode scalars() récupère les lignes sans leur enveloppe.
from sqlalchemy import select
with Session(engine) as session:
resultats = session.execute(
select(Article)
.where(Article.mots >= 700)
.order_by(Article.note.desc())
).scalars().all()
for article in resultats:
print(f"{article.titre} — note {article.note}")Étape 6 — Modifie et supprime sans sueur
Modifier un objet, c'est le muter puis committer. Supprimer, c'est une ligne. La session suit tous les changements et ne touche à la base qu'au moment du commit(), ce qui rend les rollbacks naturels en cas de pépin.
with Session(engine) as session:
article = session.get(Article, 1)
article.note = 5.0 # la mise à jour partira au commit
vieux = session.get(Article, 3)
session.delete(vieux)
session.commit()Pourquoi ça change tout pour tes projets IA
Dès que ton script manipule des données structurées — les prompts que tu envoies, les réponses des modèles, les scores d'évaluation — le SQL brut devient un boulet. Avec SQLAlchemy, ton code reflète ton domaine : tu manipules des objets Prompt, Reponse, Evaluation, et la base suit derrière. Le même code passe de SQLite en local à PostgreSQL en production en changeant une seule URL de connexion, sans réécrire une requête.
À toi de jouer
Tu tiens les six gestes essentiels : moteur, modèles, création, insertion, requête, mutation. La suite logique, c'est d'ajouter des relations entre tables — un Article appartient à un Auteur via une clé étrangère — puis de brancher Alembic pour versionner ton schéma. Ton script Python vient de gagner un accès à une vraie base de données, sans une seule ligne de SQL à maintenir.






