TechSchool
Home / Django / Django Migrations

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.

Continue learning
Django model Django orm 1 Django admin manage tool