South: migraciones inversas

Una vez que pruebas las migraciones de bases de datos es muy complicado adaptarse a trabajar sin ellas. Cuando empezamos un proyecto Django uno de los primeros "requisitos" es instalar South para que haga todo este sucio trabajo.

Y no todo es bonito... normalmente estás obligado a ejecutar la migración para probar si funciona o no. Y si no funciona, sigues obligado a corregirla y volver a correr otra migración para arreglar la anterior que no funcionaba. Y este proceso puede repetirse varias veces a lo largo del desarrollo de un proyecto, con lo que al final acabas con un número muy alto de migraciones, de las cuales cierta cantidad son parches ínfimos para arreglar cualquier pequeño fallo.

Y si a todo esto le sumamos un equipo de trabajo, un repositorio de versiones y todo el flujo de trabajo que conlleva, puede ser una fuente importante de conflictos.

South schemamigration --auto --update

Imagino que a petición de la gente, en South han pensado en ello y han implementado una sencilla funcionalidad que resuelve todo este entuerto y hace más llevadero tanto el probar los cambios como la resolución de esos pequeños fallos que puedan surgir sin llenar de paja nuestro histórico. Se trata de la opción --update.

Para ponerlo en práctica podemos hacer una migración, cometer un error de sintaxis, arreglarlo y probar como la opción --update se encarga del resto de la magia.

$ ./manage.py schemamigration app --auto --update
 + Added model app.Group
Migration to be updated, 0026_auto__add_group, is already applied, rolling it back now...
previous_migration: 0025_auto__foo (applied: 2014-01-15 19:20:47)
Running migrations for app:
  - Migrating backwards to just after 0025_auto__foo.
  < partner:0026_auto__add_group
Updated 0026_auto__add_group.py. You can now apply this migration with: ./manage.py migrate app

Lo que este comando ha hecho es hacer backward de la última migración (la 0026) a la versión anterior 0025 y reescribir la migración 0026 con los nuevos cambios. Si todavía no fuera funcional o no nos convenciera, siempre podremos repetir el comando, quedándonos en la migración 0026, hasta que estemos convencidos de que todo está correcto; momento en el cual ya estaríamos capacitados para interactuar con el servidor de versiones correspondiente (commit/push).

Un poco más sobre las migraciones inversas

Esta tarde, trabajando con Borja, además del punto anterior se dió la circunstancia de que, habiendo partido del código actualizado de nuestro proyecto, ambos tuvimos que hacer una nueva migración en nuestros entornos de desarrollo; con lo que a la hora de actualizar los cambios, uno de los dos tendría que deshacer su migración para aceptar la del otro y luego la suya.

La última migración era la 0015, y ambos hicimos la 0016 en nuestros entornos de trabajo. En el momento de actualizar el código tomamos la decisión de que yo hiciera commit de los cambios y Borja se encargaba de arreglar el entuerto.

Pensamos que iba a ser más complicado, pero el proceso fue sencillo: migrar la aplicación hacia atrás a la versión 0015, eliminar la 0016 de disco, hacer pull de los cambios, aplicar la 0016 que había commiteado yo, hacer un schemamigration --auto para que generase la 0017 de Borja y, para finalizar, migrar la aplicación a la 0017, asegurarnos de que todo está correcto y, como paso final, enviar los cambios al servidor de versiones para yo poder aplicar también la 0017 en mi entorno de desarrollo:

$ ./manage.py migrate app 0015
$ rm app/migrations/0016_auto__add_whatever.py
$ darcs pull
$ ./manage.py migrate app 0016
$ ./manage.py schemamigration app --auto
$ ./manage.py migrate app 0017
$ darcs record

He recreado el proceso de memoria, (si se me olvida algo seguro que Borja hará buen uso de los comentarios). Personalmente pensé que sería más complejo que hacer un backward y eliminar un archivo (pensé que había que tocar la base de datos para eliminar el registro correspondiente de la tabla south_migrationhistory, pero se ve que no).

Y hasta aquí el capítulo de hoy, dos formas distintas de hacer migraciones inversas con South - con casuísticas distintas - sin morir en el intento. Ya ha merecido la pena el día.

django code

About the author

Óscar
has doubledaddy super powers, father of Hugo and Nico, husband of Marta, *nix user, Djangonaut and open source passionate.