logo oujood
🔍

Les migrations dans Django

Les migrations sont le mécanisme Django pour faire évoluer la structure de la base de données en synchronisation avec vos modèles Python. Ce chapitre explique comment les créer, les appliquer, les inspecter et revenir en arrière quand c'est nécessaire.

OUJOOD.COM

Pourquoi les migrations existent

Un modèle Django est une classe Python — la base de données, elle, travaille avec des tables SQL. Les migrations sont le pont entre les deux. Chaque fois que vous modifiez un modèle (ajout de champ, suppression, changement de type), Django génère un fichier de migration qui traduit ce changement en instructions SQL. Vous n'écrivez pas ce SQL manuellement : Django s'en charge.

L'autre intérêt des migrations : elles forment un historique versionné de l'évolution de votre base de données. Cet historique peut être partagé avec l'équipe via Git, rejoué sur un nouveau serveur, ou partiellement annulé si quelque chose tourne mal.

Les deux commandes fondamentales

Toute modification de modèle passe par deux commandes dans l'ordre, sans exception.

makemigrations — détecter les changements

makemigrations compare l'état actuel de vos modèles avec l'état enregistré dans les fichiers de migration existants. S'il détecte une différence, il génère un nouveau fichier dans le dossier migrations/ de l'application concernée.

  📋 Copier le code

# Génère les migrations pour toutes les applications modifiées
python manage.py makemigrations

# Ou cibler une application spécifique
python manage.py makemigrations membres

La sortie vous indique ce qui a été détecté :

  📋 Copier le code

Migrations for 'membres':
  membres/migrations/0002_membres_telephone.py
    - Add field telephone to membres

Django numérote les migrations automatiquement : 0001_initial.py, 0002_..., 0003_.... Ces fichiers doivent être commités dans votre dépôt Git — ils font partie du projet.

migrate — appliquer les migrations

migrate lit les fichiers de migration en attente et les exécute contre la base de données. Django tient un registre interne des migrations déjà appliquées — il ne rejoue jamais deux fois la même.

  📋 Copier le code

# Applique toutes les migrations en attente
python manage.py migrate

# Ou cibler une application
python manage.py migrate membres

  📋 Copier le code

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, membres, sessions
Running migrations:
  Applying membres.0002_membres_telephone... OK

Inspecter les migrations

Voir l'historique avec showmigrations

showmigrations liste toutes les migrations du projet avec leur statut : [X] si appliquée, [ ] si en attente.

  📋 Copier le code

python manage.py showmigrations membres

  📋 Copier le code

membres
 [X] 0001_initial
 [X] 0002_membres_telephone
 [ ] 0003_membres_adresse

Voir le SQL généré avec sqlmigrate

sqlmigrate affiche les instructions SQL qu'une migration va exécuter, sans les appliquer. Utile pour auditer une migration avant de la lancer en production.

  📋 Copier le code

python manage.py sqlmigrate membres 0001

  📋 Copier le code

BEGIN;
CREATE TABLE "membres_membres" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
    "prenom" varchar(255) NOT NULL,
    "nom" varchar(255) NOT NULL,
    "mail" varchar(255) NOT NULL
);
COMMIT;

Revenir en arrière sur une migration

Django permet de dépiler des migrations — c'est-à-dire revenir à un état antérieur. Il suffit de passer le numéro de migration cible à migrate :

  📋 Copier le code

# Revenir à l'état après 0001 (annule 0002 et suivantes)
python manage.py migrate membres 0001

# Annuler toutes les migrations d'une application
python manage.py migrate membres zero

Attention : revenir en arrière sur une migration qui supprime des colonnes ou des tables entraîne une perte de données irréversible. Faites toujours une sauvegarde de la base avant de dépiler des migrations en production.

Cas courants et bonnes pratiques

Ajouter un champ à un modèle existant

Quand vous ajoutez un champ à une table qui contient déjà des données, Django a besoin de savoir quelle valeur donner aux enregistrements existants. Deux options : définir une valeur par défaut avec default=, ou autoriser la valeur nulle avec null=True.

  📋 Copier le code

class Membres(models.Model):
    prenom    = models.CharField(max_length=255)
    nom       = models.CharField(max_length=255)
    mail      = models.CharField(max_length=255)
    # Nouveau champ avec valeur par défaut pour les enregistrements existants
    telephone = models.CharField(max_length=20, blank=True, default='')

Après cette modification, lancez makemigrations puis migrate. Django génère le fichier 0002_membres_telephone.py et ajoute la colonne à la table.

Ne jamais modifier un fichier de migration à la main

Les fichiers dans migrations/ sont générés automatiquement. Les modifier manuellement sans savoir exactement ce qu'on fait désynchronise l'état Django de l'état réel de la base — ce qui provoque des erreurs difficiles à déboguer. Si une migration est incorrecte, annulez-la avec migrate, supprimez le fichier et régénérez-la.

Par carabde | Mis à jour le 05 mai 2025