Django, forcing a specific migration

Migrations are awesome magic, until the magic fails. Then it’s an awesomely frightening engine of change that threatens to wipe out your entire database.

So, before doing what I say, backup your database.

I had to enforce a “unique=True” constraint on a model. Migrations are supposed to automatically create a constraint in SQL, as well as its implied index. A quick look at the indexes (SHOW INDEXES FROM Model) didn’t show the index.

I grepped through the migrations directory and found that migration 0016 contained the change to add the index. I had some problems with migrations at that point, so it probably didn’t get applied.

The fix is to go back to state 0015, which precedes 0016, and then run migration 0016, and then run through the rest. While that sounds straightforward – you risk losing data as columns are dropped.

So I ended up using the –fake feature, which manipulates the state to appear as if we moved to a specific state. Once there, I applied 0016, and then faked my way back to the final state.

./manage.py migrate --fake appname 0015
./manage.py migrate appname 0016
./manage.py migrate --fake appname

It seemed to work. (BTW, you have to delete dupes in the Model table before running the migration.) (Also, upon migrating, the app stopped working, as expected, because an insert failed.)