Django Migrations
We have a model created now, but the database has no tables to store it.
Django's migration tool is built-in, and each app keeps its migrations in a migrations/ folder next to its models.
A migration is generated and then applied: makemigrations writes the file, and migrate runs it.
Generate Migrations with makemigrations
Now we'll generate a migration for Animal:
uv run manage.py makemigrations
Migrations for 'animals':
animals/migrations/0001_initial.py
+ Create model Animal
The accounts app's migration, for our user model, came with the starting branch.
Review the Migration
It's a best practice to look at a generated migration after creating it, before applying it to the database. Ours for Animal is in animals/migrations/0001_initial.py, if you want to read it.
Apply Migrations with migrate
Now we'll apply our migrations:
uv run manage.py migrate
The output also lists the migrations of the built-in apps startproject installed.
Committing Migrations
Migration files are part of our code, so we commit each one together with the model change it came from. When a teammate pulls that commit, or a server deploys it, migrate applies the same change to their database. Every copy ends up with the same tables.
How do I undo a migration?
Run migrate with the app's name and the migration just before the one you want to undo. Once animals has a 0002 migration, this unapplies 0002:
uv run manage.py migrate animals 0001
Unapplying a migration leaves its file in migrations/, so the next migrate would apply it again. To replace the migration with a new one:
uv run manage.py migrate animals 0001
rm animals/migrations/0002_*.py
uv run manage.py makemigrations
uv run manage.py migrate animals zero unapplies every migration in the app.