Thursday, December 9, 2010

Django and database migrations using South


Currently I am working on a Django project that uses multiple databases. To migrate the databases automatically when the asscoiated models change, we use South. Unfortunately South cannot handle ForeignKeys between models from different databases, see this thread on the South Users Google Group. When South tries to execute the migration step that introduces such a relationship, it aborts the migration and leaves me with an incomplete database. This also causes a problem when running unit tests as South's test runner integration will try to build the database and fail. Consequently, no tests are run.

It is very easy to work around this:

  1. Disable South's test runner integration: set the option SOUTH_TESTS_MIGRATE in settings.py to False

  2. Disable South in you Django project: remove 'south' from the tuple of installed apps (in settings.py)

  3. Create the database using Django's syncdb: bin/django syncdb

  4. Enable South: add 'south' to the tuple of installed apps (in settings.py)

  5. Fake the migration up to the last step: bin/django migrate <app> --fake

South uses a special table in your database to register which migrations have been performed, south_migrationhistory. After the last step this tables contains all the steps.