Database Migrations with Django
Migrations can be tricky with Django and can get hairy when not navigated precisely.
Django offers four management commands related to migrations:
- makemigrations — used to make migration files from current data models
- migrate — used to migrate migration files to the configured database
- showmigrations — used to show migrations that have and have not been run on the database
- squashmigrations — used to squash multiple migration files into a single migration file
Let’s say we’ve adjusted our data models and it is time to make a migration file and migrate the newly adjusted models to the database.
We might try something like this:
./manage.py makemigrations
./manage.py migrate
However, if we are only intending to make migrations for a specific app within our django project, or only intending to run migrations for a specific app within our project, then we can run the previous commands with an app_name argument like so:
./manage.py makemigrations app
./manage.py migrate app
It might be the case that we would like to revert the database back to a previous migration after we have already run our migrations, in this case we can add an extra argument to rollback to the specific migration for a specific app like so:
./manage.py migrate app migration_file_name
In practice, this may look something like this:
./manage.py migrate app 0002_auto_20170808_2327
We can rollback all migrations for a specific app with the “zero” argument like so:
./manage.py migrate app zero
Keeping track of the migrations that have been run for all of the apps within a django project can be tough; thankfully, django offers the showmigrations command to allow developers to view the migrations that have and have not been run.
./manage.py showmigrations appapp
[X] 0001_initial
[X] 0002_auto_20170831_2151
[X] 0003_auto_20170831_2247
[X] 0004_auto_20170901_2016
[ ] 0005_auto_20170901_2116
This tells us that migrations 0001_initial through 0004_auto_20170901_2016 have been migrated, and that migration 0005_auto_20170901_2116 has not been migrated and is still just a migration file in the application’s migrations directory.
It’s possible that multiple migrations will be made while building out a feature; we can squash these migrations before pushing to source control like so:
./manage.py squashmigrations app earliest_migrations_file_name latest_migrations_file_name
The command above will squash all migrations between earliest_migrations_file_name and latest_migrations_file_name into a single migrations file. If we want to squash up migrations from the initial migration including and prior to a single file, we can drop the latest_migrations_file_name argument and use:
./manage.py squashmigrations app earliest_migrations_file_name
This will squash all migrations between and including the initial migration and the named earliest_migrations_file_name.
Good luck with Django migrations!