Django South, listando, merge y arreglando estropicios varios

(english version)

Si tienes un proyecto en Django en el que trabajan varias personas bajo un repositorio es común que  hagáis cambios en la base de datos de forma más o menos simultánea y cuando luego en  «pre»/staging o lo que es peor directamente en producción haces el «./manage.py migrate app» y sale el siguiente Traceback, es cuando empienzan los sudores de la muerte 😉 (el app en este ejemplo se llama «main»)

Running migrations for main:
 ! Migration main:0048_auto__add_field_reseller_cdn_css__add_field_reseller_cdn_js__add_field should not have been applied before main:0047_auto__add_securitylevelfile but was.
Traceback (most recent call last):
 File "./manage.py", line 11, in <module>
 execute_manager(settings)
 File "/usr/lib/python2.5/site-packages/django/core/management/__init__.py", line 438, in execute_manager
 utility.execute()
 File "/usr/lib/python2.5/site-packages/django/core/management/__init__.py", line 379, in execute
 self.fetch_command(subcommand).run_from_argv(self.argv)
 File "/usr/lib/python2.5/site-packages/django/core/management/base.py", line 191, in run_from_argv
 self.execute(*args, **options.__dict__)
 File "/usr/lib/python2.5/site-packages/django/core/management/base.py", line 220, in execute
 output = self.handle(*args, **options)
 File "/usr/lib/python2.5/site-packages/South-0.7.3-py2.5.egg/south/management/commands/migrate.py", line 105, in handle
 ignore_ghosts = ignore_ghosts,
 File "/usr/lib/python2.5/site-packages/South-0.7.3-py2.5.egg/south/migration/__init__.py", line 185, in migrate_app
 raise exceptions.InconsistentMigrationHistory(problems)
south.exceptions.InconsistentMigrationHistory: Inconsistent migration history
The following options are available:
 --merge: will just attempt the migration ignoring any potential dependency conflicts.
aloja:/var/www/virtual/guardatum.com/guardatum_code# ./manage.py migrate 0054 main
Traceback (most recent call last):
 File "./manage.py", line 11, in <module>
 execute_manager(settings)
 File "/usr/lib/python2.5/site-packages/django/core/management/__init__.py", line 438, in execute_manager
 utility.execute()
 File "/usr/lib/python2.5/site-packages/django/core/management/__init__.py", line 379, in execute
 self.fetch_command(subcommand).run_from_argv(self.argv)
 File "/usr/lib/python2.5/site-packages/django/core/management/base.py", line 191, in run_from_argv
 self.execute(*args, **options.__dict__)
 File "/usr/lib/python2.5/site-packages/django/core/management/base.py", line 220, in execute
 output = self.handle(*args, **options)
 File "/usr/lib/python2.5/site-packages/South-0.7.3-py2.5.egg/south/management/commands/migrate.py", line 78, in handle
 apps = [Migrations(app)]
 File "/usr/lib/python2.5/site-packages/South-0.7.3-py2.5.egg/south/migration/base.py", line 60, in __call__
 self.instances[app_label] = super(MigrationsMetaclass, self).__call__(app_label_to_app_module(app_label), **kwds)
 File "/usr/lib/python2.5/site-packages/South-0.7.3-py2.5.egg/south/migration/utils.py", line 41, in app_label_to_app_module
 app = models.get_app(app_label)
 File "/usr/lib/python2.5/site-packages/django/db/models/loading.py", line 140, in get_app
 raise ImproperlyConfigured("App with label %s could not be found" % app_label)
django.core.exceptions.ImproperlyConfigured: App with label 0054 could not be found

No hagáis el «–merge» que os recomienda. Lo que hay que hacer es mostrar un listado del histórico de migraciones y ver cuáles son las que se han quedado colgadas:

( ) 0047_auto__add_securitylevelfile
 (*) 0048_auto__add_field_reseller_cdn_css__add_field_reseller_cdn_js__add_field
 (*) 0049_auto__add_field_orders_admin
 (*) 0050_auto__del_field_orders_admin
 () 0051_auto__add_field_customer_notify_reseller

Como vemos la 0047 es la que nos está rompiendo la coherencia. Lo que hacemos es marcarla como que ya está hecha esa migración, ya que en el pasado efectivamente ya realizamos la 0047 😉

./manage.py migrate main --fake 0047_auto__add_securitylevelfile

otro list para ver cómo ha quedado:

./manage.py migrate --list
(*) 0047_auto__add_securitylevelfile
 (*) 0048_auto__add_field_reseller_cdn_css__add_field_reseller_cdn_js__add_field
 (*) 0049_auto__add_field_orders_admin
 (*) 0050_auto__del_field_orders_admin
 () 0051_auto__add_field_customer_notify_reseller

Y el migrate final:

./manage.py migrate main

También puedes ir un poco más a lo bruto y resetear completamente South.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *