Squash Migrations in Django

by Mukhammad Karimov


Posted on Sun 17 November 2019



Introduction

If you have been working on Django based web application, you will end up having dozens of migration files. Though it doesn't affect the application performance at all, it'll take time to apply them all if you spinning up with new database. Sometimes having a single fresh migration file per app is desirable. In this article, we will be addressing two known methods to achive that 😎.

Method One

Official Django Documentation recommends squashing migrations.

Steps

  1. Squash existing migrations. Run django-admin squashmigrations.
  2. Apply new squashed migration file(s). Run django-admin migrate
  3. Delete old migrations, keep squashed migration(s) only.

Squashed migrations are special because they: - have word squashed in the filename. - are not dependatant to previous ones. - are marked as initial=True which indicates this is a new initial migration - have replaces=[...] attribute that includes migrations merged.

In Production

Things get little complicated when you are working on real-world production application with a team of developers. You have to take an extra caution. 1. Make sure to apply unapplied migrations before Squashing. 2. Test on one of your co-workers local machine. This requires your team to be aligned. 3. Keep all of your migrations until squashed migration file(s) got successfully applied to staging, testing, and production database. If things go wrong, you will be able to revert back.

Drawbacks

squashmigrations command might fail and result in CircularDependencyError which is pretty common, however, Django Documentation gives a solution to resolve it 🥳.

Method Two

This method is similar to above, but you pretend you have written all models at once and have never ever had any migrations applied.

Steps

  1. Delete existing migration files, keep migrations folder empty with only migrations/__init__.py.
  2. Remove all records from django migrations table in database. Run django-admin dbshell and execute TRUNCATE django_migrations; query.
  3. Create new migration files. Run django-admin makemigrations.
  4. Apply new migrations with fake flag. Run django-admin migrate --fake

In Production

Repeat the steps several times and know exactly what you are doing.

Drawbacks

This method requires you to write SQL query and execute directly which is risky and you might accidentally drop a table/database instead 🤯.

Conclusion

You dont have to bother with your migrations and never touch them at all. If have hundreds of migration files and you want to clean them up, try one of the ways above. I just shared my experience with you. Happy coding👨‍💻!!!


About me
Generic placeholder image

Mukhammad Karimov

I'm a Software Developer at Super Dispatch (TechStars '16). First graduate of Inha University in Tashkent, young prominent blogger, and pythonista. I write about programming, life hacks, and sometimes travel experience.

Categories