During development I created many migrations, often going back and forth about how I wanted to implement something.
Now it is time to push it to production, but I am getting errors when replaying all the migrations on the virgin database.
I ended up doing the following to get it to work.
python manage.py syncdb --all
python manage.py migrate --fake
But that will not apply a data migration that I created.
Upon further thinking, I decided that I wanted to squash all my migrations into just one, when I am ready to tag this as a release version.
How can I do this? If it is not possible/recommended, then what is the prefered method?
Have you tried deleting all migrations, then doing
./manage.py schemamigration myapp --init
?Remember, this will break anything that relies on those migrations, so only do it if you are not in production yet.
It's possible, and I've done it myself a few times. You basically have two methods:
1) This is by far the easiest and preferred method. Simply, rollback your dev database to right before the first migration you want to include in the "squash", then delete all the migrations from that one on. Finally, re-run the schemamigration management command. You'll end up with all the migrations necessary all in one file.
2) If for some reason you can't do #1, it's still technically possible, but will be much more exacting of a procedure. Literally copy and paste the contents of the forwards and backwards methods of each migration into one migration file (your lowest numbered one). That part is easy enough, but you'll then have to also make manual modifications to the frozen models at the bottom of the file. I've found the best way is to simply try to run this new migration. You'll likely get errors about such-and-such model has no attribute such-and-such. That's a signal to go add that field to the frozen model. When the migration runs without errors, you're golden.
Note: Remember when you delete those old migration files, delete them with the any versioning system you're using in mind. In other words, use
git rm
orsvn rm
, etc. If you end up with those old migrations tagging along in your release, you'll bork your production instance. For my part, I never commit migrations until I'm ready to release my changes. You can always regenerate the migration if you lose it.There is a command in the django manage.py specifically for this. If you are using Migrations as fixtures you might need to fiddle with the dependencies attribute in some of the Migrations if you don't wish to squash your fixtures.
If you have no fixtures and simply want to squash all the migrations from you can run:
Where app_name is the name of your app, and 0001 is the migration you wish to squash up to.
See the docs linked above for more information.