Guide complet — installation, audit, réparation, cron et production
Migration Repair Doctor v1.5 — réparer les migrations Django partiellement appliquées
Ce guide explique comment installer et utiliser migration_repair_doctor, une commande Django conçue pour comparer l’état des modèles Django, les fichiers de migrations, la table django_migrations et le schéma réel MySQL/MariaDB. La version 1.5 ajoute le mode central --repair-partial, qui enchaîne automatiquement nettoyage de migration cible, fake-record contrôlé, génération d’une migration follow-up, migration et vérification finale.
1. Le problème que ce cron résout
Les migrations Django sont fiables quand tout se passe parfaitement. Elles deviennent beaucoup plus pénibles quand une migration est partiellement exécutée : une table a été créée, quelques colonnes aussi, un ou deux index ont échoué, mais la migration n’a pas été enregistrée dans django_migrations. Au run suivant, Django retente toute la migration et plante.
Tables déjà créées
Le SQL a matérialisé des tables, mais Django pense que la migration n’est pas appliquée.
Colonnes partielles
Certaines colonnes existent, d’autres manquent encore, notamment des FK ajoutées après CreateModel.
Index trop longs
MySQL/MariaDB refuse les index sur VARCHAR/TEXT trop longs, typiquement avec utf8mb4.
Ce que le script sait faire
| Fonction | Option | Utilité |
|---|---|---|
| Vérifier l’état DB vs models.py | --verify | Liste les colonnes, index ou tables manquantes, et peut générer une migration follow-up. |
| Scanner les migrations | --scan / --explore | Trouve la migration la plus probablement cassée avec un scoring. |
| Nettoyer une migration cible | --clean-target-migration | Réécrit la migration avec les opérations réellement matérialisées en DB. |
| Marquer appliqué | --fake-record | Insère l’entrée dans django_migrations après nettoyage contrôlé. |
| Réparation complète | --repair-partial | Workflow automatisé en 5 étapes pour migrations partiellement appliquées. |
| Exporter les diagnostics | --export excel / --export pdf | Produit un rapport exploitable pour audit, support ou historique. |
2. Installation
2.1 Télécharger le script
Le fichier publié est disponible ici :
/static/toolbox/migrationrepair_doctor.py⬇ Télécharger migrationrepair_doctor.py
2.2 Installer dans une app Django
your_app/
management/
__init__.py
commands/
__init__.py
migration_repair_doctor.py2.3 Dépendances Python
Le script utilise Django, openpyxl pour l’export Excel et reportlab pour l’export PDF.
pip install openpyxl reportlab2.4 Vérifier que Django voit la commande
python manage.py help migration_repair_doctor
python manage.py migration_repair_doctor --help2.5 Premier test sans risque
Par défaut, si ni --execute ni --simulation ne sont fournis, le script bascule en simulation.
python manage.py migration_repair_doctor \
--app tech_glossary \
--verify \
--verbose2.6 Checklist avant production
Backup Git
Les fichiers de migration peuvent être réécrits. Commit ou backup obligatoire avant execute.
Backup SQL
Le script ne fait pas de dump SQL complet. Fais-le côté infrastructure si tu es en production.
Permissions
L’utilisateur Django doit pouvoir lire information_schema et modifier django_migrations.
Chemin backup
Par défaut : C:/temp/migration_repair_doctor_backups sous Windows, /tmp/migration_repair_doctor_backups sous Linux.
3. Commandes rapides à retenir
3.1 Vérifier une app
python manage.py migration_repair_doctor \
--app tech_glossary \
--verify \
--verbose3.2 Générer une migration follow-up si verify détecte des colonnes/champs manquants
python manage.py migration_repair_doctor \
--app tech_glossary \
--verify \
--execute \
--verbose
python manage.py migrate tech_glossary
python manage.py migration_repair_doctor \
--app tech_glossary \
--verify \
--verbose3.3 Réparer une migration partiellement appliquée en simulation
python manage.py migration_repair_doctor \
--app tech_glossary \
--repair-partial \
--simulation \
--verbose3.4 Réparer réellement une migration partiellement appliquée
python manage.py migration_repair_doctor \
--app tech_glossary \
--repair-partial \
--execute \
--verbose3.5 Réparer une migration précise
python manage.py migration_repair_doctor \
--app tech_glossary \
--target 0014 \
--repair-partial \
--execute \
--verbose3.6 Exporter un rapport Excel ou PDF
python manage.py migration_repair_doctor \
--app tech_glossary \
--scan \
--export excel \
--open-export \
--verbose4. Mode indispensable : --repair-partial
C’est le mode à utiliser quand une migration a été interrompue pendant son exécution. Exemple : MySQL a créé une table, puis a échoué sur un index trop long. Django n’a pas enregistré la migration, donc au prochain run il retente de créer la table et casse.
4.1 Workflow interne en 5 étapes
4.2 Commande standard
python manage.py migration_repair_doctor \
--app your_app \
--repair-partial \
--execute \
--verbose4.3 Commande prudente avec target
python manage.py migration_repair_doctor \
--app your_app \
--target 0050 \
--repair-partial \
--execute \
--verbose4.4 Résultat attendu
REPAIR PARTIAL MIGRATION WORKFLOW
App: your_app
Mode: EXECUTE
STEP 1/5 - Clean target migration
Backup created: ...
Rewritten cleaned migration: ...
STEP 2/5 - Fake-record cleaned migration
Recorded migration as applied: your_app.0050_...
STEP 3/5 - Generate follow-up sync migration
Generated migration: 0051_your_app_manual_field_sync.py
Verification failed as expected before follow-up migration is applied.
STEP 4/5 - Run migrate
Applying your_app.0051_your_app_manual_field_sync... OK
STEP 5/5 - Final verification
Errors count : 0
Pending AddField : 0
Pending AlterField: 0
Pending AddIndex : 0
Pending CreateModel: 0
Status: OK
REPAIR PARTIAL WORKFLOW COMPLETED5. Référence CLI des options importantes
| Option | Type | Description | Exemple |
|---|---|---|---|
| --app | required | App Django à inspecter. | --app tech_glossary |
| --target | safe | Préfixe ou nom exact de migration. | --target 0014 |
| --last | safe | Utilise la dernière migration sur disque. | --last |
| --scan / --explore | safe | Scanne et score les migrations suspectes. | --scan --verbose |
| --verify | safe | Vérifie DB vs models.py. Avec --execute, génère une migration follow-up. | --verify --execute |
| --clean-target-migration | mutate | Réécrit la migration cible nettoyée. | --target 0050 --clean-target-migration --execute |
| --fake-record | mutate | Enregistre la migration cible dans django_migrations. | --fake-record --execute |
| --repair-partial | workflow | Réparation complète des migrations partiellement appliquées. | --repair-partial --execute |
| --safe-threshold | safe | Longueur maximale sûre pour index CharField MySQL/MariaDB. Défaut : 191. | --safe-threshold 191 |
| --export | safe | Exporte rapport en Excel, PDF ou les deux. | --export both --open-export |
| --backup-dir | safe | Dossier de backup des migrations réécrites. | --backup-dir C:\temp\mr_backups |
| --simulation | safe | Affiche ce qui serait fait sans modifier disque/DB. | --repair-partial --simulation |
| --execute | mutate | Autorise les écritures disque/DB. | --execute |
6. Cas d’usage et séquences exactes
Cas A — erreur MySQL 1071 : clé trop longue
Symptôme : MariaDB/MySQL refuse un index sur un champ long, souvent CharField(260), URLField ou TextField.
python manage.py migration_repair_doctor \
--app your_app \
--repair-partial \
--simulation \
--verbose
python manage.py migration_repair_doctor \
--app your_app \
--repair-partial \
--execute \
--verboseCas B — tables créées mais migration non appliquée
python manage.py migration_repair_doctor \
--app your_app \
--scan \
--verbose
python manage.py migration_repair_doctor \
--app your_app \
--repair-partial \
--execute \
--verboseCas C — colonnes FK manquantes après fake-record
Ce cas arrive quand la migration a été marquée appliquée alors que certaines colonnes n’existent pas encore.
python manage.py migration_repair_doctor \
--app your_app \
--verify \
--execute \
--verbose
python manage.py migrate your_app
python manage.py migration_repair_doctor \
--app your_app \
--verify \
--verboseCas D — diagnostic seulement, aucun changement
python manage.py migration_repair_doctor \
--app your_app \
--scan \
--export excel \
--open-export \
--verboseCas E — migration précise connue
python manage.py migration_repair_doctor \
--app your_app \
--target 0050 \
--clean-target-migration \
--fake-record \
--execute \
--verbose
python manage.py migration_repair_doctor \
--app your_app \
--verify \
--execute \
--verbose
python manage.py migrate your_app7. Cron, CI et exploitation
7.1 Cron quotidien de vérification
# Tous les jours à 03:20
20 3 * * * cd /var/www/ideo_lab && /opt/venv/bin/python manage.py migration_repair_doctor --app tech_glossary --verify --verbose >> /var/log/ideo_lab/migration_repair_doctor.log 2>&17.2 CI avant déploiement
python manage.py migration_repair_doctor --app tech_glossary --verify --verbose
python manage.py showmigrations tech_glossary7.3 Runbook production en cas d’incident
8. Dépannage
Erreur : Use either --simulation or --execute, not both
Le script refuse les modes ambigus. Garde un seul des deux flags.
# Bon
python manage.py migration_repair_doctor --app your_app --repair-partial --simulation
# Bon
python manage.py migration_repair_doctor --app your_app --repair-partial --executeErreur : No materialized operations detected
Le script ne voit aucune table/colonne réellement présente pour construire une migration nettoyée. Soit la mauvaise migration est ciblée, soit la DB n’a rien matérialisé.
python manage.py migration_repair_doctor --app your_app --scan --verbose
python manage.py showmigrations your_appVerify affiche des warnings d’index manquants mais Status: OK
Ce n’est pas bloquant si les erreurs sont à zéro. Les warnings signalent des index déclarés côté modèle mais non présents côté DB, ou renommés par MySQL.
Le follow-up est généré mais migrate échoue
Lis la migration générée, puis vérifie si le champ ajouté est nullable, a une default, ou référence une table absente.
python manage.py showmigrations your_app
python manage.py sqlmigrate your_app 0051
python manage.py migrate your_appRègles MySQL/MariaDB à garder
| Champ | Index direct ? | Conseil |
|---|---|---|
| CharField <= 191 | Oui | OK en utf8mb4. |
| CharField 220/260/500 | Non | Utiliser hash court ou index applicatif. |
| TextField | Non | Jamais d’index BTree direct standard. |
| URLField long | Non | Indexer un hash ou une clé courte. |
| ForeignKey | Oui | Index automatique généralement créé par Django/MySQL. |
| Symptôme | Première commande | Action suivante |
|---|---|---|
| Tu veux juste auditer | --verify --verbose | Lire erreurs, warnings, pending fields/indexes. |
| Migration interrompue, tables créées | --repair-partial --simulation | Si plan cohérent, relancer avec --execute. |
| Migration précise connue | --target 00XX --repair-partial | Évite les erreurs de détection automatique. |
| Colonnes manquantes mais migrations appliquées | --verify --execute | Génère une migration follow-up puis migrate. |
| Index trop long 1071 | --repair-partial | Corriger ensuite models.py pour supprimer l’index dangereux. |
| Tout est OK | --verify | Conserver le rapport et ne rien modifier. |
