migrations avec alembic ======================= .. warning :: Les migrations ne sont pas appliquées à une nouvelle installation. Ne pas compter dessus pour initialiser la BDD. Pour ça, regarder du côté du `script populate/syncdb`_. .. _script populate/syncdb: https://framagit.org/endi/endi/-/blob/master/endi/models/populate.py Créer des migrations --------------------- .. note :: Il est possible de grouper **schema migration** et **data migration** dans un même fichier de migration si pertinent. Évolution de structure de la BDD (schema migration) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. warning :: La création de nouvelle table est automatique et ne nécessite pas de migration. Dans l'ordre : 1. Modifier les modèles (ex: ajout/retrait/renommage de colones). 2. Créer une migration avec détection auto des modifications .. code-block:: console endi-migrate development.ini revision --m 'Description de la migration' 3. Faire le ménage dans les changements détectés pour ne garder que ceux pertinents, dans le ``upgrade()`` comme dans le ``downgrade()``… Ou carrément de modifier ce qu'a détecté alembic, car il a ses limites (ex: ne détecte pas le renommage de table). Évolution des données (data migration) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ En général il est plus simple de partir d'une migration vide : .. code-block:: console endi-migrate development.ini revision --empty --m 'Description de la migration' .. note:: ``op.execute()`` et ``conn.execute()`` permettent d'exécuter du code SQL tous les deux. ``op.execute()`` demande moins de code (on gagne le get_bind) mais ne permet pas de récupérer le résultat de la requête. Pour les ``SELECT`` il faut donc utiliser ``conn.execute`` Quelques conseils pour les **data migrations** : * Même si c'est tentant, ne pas importer les modèles dans les migrations (car aucune garantie de leur stabilité dans le temps), mieux vaut faire du SQL brut. Exception : le modèle ``endi.models.config.Config`` dont on sait qu'il ne bougera pas trop. * Ne pas oublier ``mark_changed(session)`` et ``session.flush()`` après un ``*.execute()`` sans quoi les modifications opérées dans la migration seront sans effet… * Tenter de limiter le nombre de requêtes (éviter les boucles avec un ``execute()`` à chaque tour). C'est toujours ça de temps de déploiement / mise à jour gagné… Liens ----- * Doc de ``op.execute()`` : https://alembic.sqlalchemy.org/en/latest/ops.html?highlight=execute#alembic.operations.Operations.execute