= Django III : Faire évoluer ses données = <> == Introduction == Tout au long de la vie d'un projet, l'étape de la mise à jour est souvent incontournable, et il existe des outils pour nous faciliter sa mise en oeuvre. Ici, on s'intéresse aux mises à jour qui impliquent des modifications de structures de données et de données elles-mêmes. [[http://south.aeracode.org/|South]] est un paquet Django qui apporte un framework de migrations, et des outils pour générer ces migrations. === Objectifs === * Comprendre l'utilité d'un framework de migrations * Utiliser South * Implanter South dans son application Django === Prérequis techniques === * Démarrer un projet Django ([[ Python/buildout ]]) * Créer une application Django ([[ SupportFormation/Django I ]]) * Construire un Modèle Django ([[ SupportFormation/Django I ]]) * Construire une Admin Django ([[ SupportFormation/Django II ]]) === Ressources === * [[http://south.readthedocs.org/en/latest/ | Documentation South]] == Travaux pratiques == === Création d'un modèle simple === Dans votre nouvelle application, ajouter un modèle Django simple, avec seulement 1 champs texte 'titre'. Pour ajouter du contenu, créer une admin Django pour ce modèle. Ajouter quelques contenus. === Préparer notre application pour le framework de migration === ==== Installer South ==== Si vous avez utilisé le squelette de projet de l'AUF, vous n'avez rien à faire, South est déjà configuré comme il faut. Autrement, Ajouter le egg 'South' dans les dépendances du buildout et ajouter 'south' dans settings.INSTALLED_APPS. (cf. documentation de South) ==== Coupler notre application à South ==== Avant de faire quelconques modifications de notre modèle, il faut dire à Django que les modèles de notre applicationsont géré par South : {{{ bin/django schemamigration --initial }}} Dans l'application, un répertoire '''migrations''' a été ajouté avec un fichier préfixé par '''0001_'''. Si on regarde ce fichier, il décrit notre modèle. {i} Comme c'est notre première migration, on ne va pas pouvoir l'exécuter car la table existe déjà en base. {{{ bin/django migrate }}} Pour que notre système soit dans un état cohérent, nous allons faire 'comme si' la migration avait bien été exécutée. {{{ bin/django migrate 0001 --fake }}} === Utilisation classique de South === Nous vous à présent, disposer d'un champs 'description'. Par défaut, Django n'est pas capable de modifier une structure de données. Il est nécessaire soit de détruire la table en question puis faire un {{{ bin/django syncdb }}} ou faire un {{{ bin/django reset }}} qui détruit tous les modèles de l'app et les recrée. /!\ Dans les 2 cas, '''on perd TOUT le contenu''', ce qui n'est pas envisageable pour un système en production! ==== Modifier le modèle ==== Dans le fichier models.py de votre application, ajouter le champs 'description'. Nous sommes donc dans un état où le modèle à changé, mais la structure de la base ne reflète pas ces changements. Générer la migration qui permettra de faire cette modification automatiquement : {{{ bin/django schemamigration --auto }}} Dans le répertoire '''migrations''', un fichier préfixé par '''0002_''' a été ajouté. Il contient le code capable d'ajouter le champs description à la table du modèle dans le SGBD. Consultons l'état de nos migrations par rapport à la base de données : {{{ bin/django migrate --list }}} affiche quelque chose comme ceci : {{{ (*) 0001_xxxxx ( ) 0002_xxxxx }}} L'étoile signifie que la migration a été exécutée. Il nous reste donc à exécuter notre migration. {{{ bin/django migrate }}} {{{ bin/django migrate --list }}} affiche quelque chose comme ceci : {{{ (*) 0001_xxxxx (*) 0002_xxxxx }}} En retournant dans notre Admin, ou directement en explorant la table, on peut voir que le contenu est toujours présent, et que la structure a bien été changée. {i} Il est fortement conseillé de faire des migrations le plus atomique possible. ==== Migrer les données ==== Nous allons maintenant agir sur les données du modèle, et South nous facilite la tâche pour ça aussi. Nous voulons initialiser ce champs 'description' avec la valeur champs 'titre' et la valeur du champs 'id'. Géréner la migration de données : {{{ bin/django datamigration initialisation_champs_description }}} Dans le répertoire '''migrations''', un fichier '''0003_initialisation_champs_description''' a été ajouté. Il contient le code minimaliste pour écrire la migration lorsqu'elle est jouée (ou déjouée si la migration est réversible). /!\ Pour manipuler les objets du modèle, il faut utiliser le module spécial '''orm''' {{{ orm.MonModele }}} au lieu de {{{ monapp.models.MonModele }}} car ce modèle est chargé selon le contexte des migrations effectuées. Il nous reste donc à exécuter notre migration. {{{ bin/django migrate }}} == Conclusion == La procédure de déploiement devient standardiser, car il suffit de faire un {{{ bin/django migrate }}} systématiquement. Les migrations font parties intégrantes de l'application et sont versionnées. Les migrations de schéma sont du code python, et non des fichiers en SQL. * South doit être utilisé dans tout projet * Les migrations doivent être le plus atomique possible * Les migrations doivent se baser sur le le module '''orm''' * Les commandes '''schemamigration''', '''datamigration''' et '''migrate''' --help pour en savoir plus