A Django migration is a versioned Python description of database schema changes. Model changes are turned into migration files, and those files tell Django how to bring database tables into line with the models. This avoids manually writing SQL every time an application evolves. section 10.1.2 section 10.6
The basic workflow has two commands: run `python manage.py makemigrations` after changing a model to generate migration files, then run `python manage.py migrate` to apply pending scripts to the database. `migrate` can also apply built-in application migrations, such as those for admin, authentication, content types, and sessions. section 2.7 section 10.6
A migration file declares a `Migration` class with three important parts:
- `initial` marks the first migration for an app. section 10.1.1
- `dependencies` lists migrations that must run first; Django uses these dependencies rather than file numbers to determine execution order. section 10.1.1 section 10.6
- `operations` contains objects describing database work, such as `CreateModel` or `AddField`. section 10.1.1 section 10.1.2
Listing 10.3 The initial migration script for the Promoters app
# RiffMates/promoters/migrations/0001_initial.py
from django.db import migrations, models
class Migration(migrations.Migration): #1
initial = True #2
dependencies = [] #3
operations = [ #4
migrations.CreateModel( #5
name="Promoter",
fields=[ #6
(
"id", #7
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"first_name", #8
models.CharField(max_length=25)
),
("last_name", models.CharField(max_length=25)),
],
),
]
An initial migration uses `CreateModel` to describe the model’s table and fields. The file is mostly declarative data; Django contains the code that carries out the database change. section 10.1.1
Adding a required field to an existing table
Adding `famous_for = models.CharField(max_length=50)` changes the Promoter model, but existing rows need a value because the field is non-nullable. `makemigrations promoters` prompts for a one-off default; entering an empty string produces an `AddField` operation with that default for existing data. `null=True` controls whether the database accepts NULL, while `blank=True` controls whether Django Admin and forms allow an empty value. section 10.1.2 section 10.1.2
Migrations manage a database over time, when changing a live table is messier than creating one. They can run forward and backward. For changes beyond schema shape, `RunPython` can call one function during forward migration and another during backward migration; `makemigrations --empty` creates a stub for such custom work. section 10.1.2 section 10.6
Practice the full lifecycle by adding address fields, migrating them, squashing migrations, then replacing several fields with one multiline address field while converting existing data and removing the old columns. section 10.5


















