Django Migrations
This page shows how a Django model change becomes a migration file and how the migrate command applies it to the database. It gives the safe command order, the inspection tools, the reverse steps, and the common mistakes.
How a model change becomes a migration
Django compares your models to the migration files. The makemigrations command writes a new migration file for each difference. The migrate command reads the migration files and changes the database tables.
Use this order. Edit models.py first. Run makemigrations. Read the new file. Run migrate last. The file is a record of the change. The database changes only at the migrate step.
python manage.py makemigrations
python manage.py migrate
Inspect the migration plan and the SQL
The showmigrations command lists the migration files and marks the applied ones. Use it to see what the database already has. The sqlmigrate command prints the SQL for one migration. It does not run the SQL.
Read the SQL before you apply a risky change. Check the table names and the column types. The output shows the exact statements that migrate will send to the database.
python manage.py showmigrations
python manage.py sqlmigrate shop 0003
Reverse a migration
You can move an app back to an earlier migration. Give the app label and the target migration name. Django runs the reverse operations in the migration files.
The command below moves the shop app back to migration 0002. Django removes the changes from 0003. Data in the removed columns is lost. Make a backup first.
python manage.py migrate shop 0002
Write a data migration
A data migration changes rows, not the table structure. Create an empty migration first. Then add a RunPython call with a forward function and a reverse function.
The forward function fills the new field. The reverse function undoes the change. Django calls the reverse function when you reverse the migration. Keep both functions small and test them on a copy of the data.
from django.db import migrations
def fill_slugs(apps, schema_editor):
Article = apps.get_model("blog", "Article")
for article in Article.objects.all():
article.slug = article.title.lower().replace(" ", "-")
article.save()
def clear_slugs(apps, schema_editor):
Article = apps.get_model("blog", "Article")
Article.objects.update(slug="")
class Migration(migrations.Migration):
dependencies = [("blog", "0002_article")]
operations = [migrations.RunPython(fill_slugs, clear_slugs)]
Combine old migrations with squashmigrations
A project collects many small migration files over time. The squashmigrations command joins them into one file. The new file has the same final effect on the database.
Squash the files only after the old migrations are applied on every environment. Keep the old files until you test the squashed file. The command below squashes the blog app up to 0005.
python manage.py squashmigrations blog 0005
Common mistakes and fixes
Do not edit a migration that already ran. Other databases already applied the old version. The fix is a new migration with the correct change.
Commit the migration files to version control. A teammate who pulls the code without the files gets a missing migration error. The fix is to add the files in the same commit as the model change.
A model change without a migration leaves the database out of date. The app fails at runtime. The fix is to run makemigrations and then migrate before you deploy.
Common questions
What is the difference between makemigrations and migrate?
makemigrations writes a migration file from the model changes. migrate applies the migration files to the database.
How do I undo a migration?
Run migrate with the app label and the earlier migration name, for example migrate shop 0002. Django reverses the operations after that migration.
Where do I put a data migration?
Put it in the migrations folder of the app, as a normal migration file with a RunPython operation. Create the file with makemigrations --empty.