5. Database Migrations
In Django, makemigrations
and migrate
are two key management commands used for working with database schema changes.
-
makemigrations
:- This command is used to generate migration files that reflect changes made to your models (like adding or modifying fields, tables, etc.).
- When you run
makemigrations
, Django looks at the changes you’ve made to your model files (usually in themodels.py
files) and creates a migration file that describes the changes in the database schema. - It doesn’t apply any changes to the database itself but prepares the necessary migration scripts that will later be applied.
Example:
python manage.py makemigrationsThis will create new migration files under the
migrations
folder of the corresponding app. -
migrate
:- This command is used to apply the migrations (including those generated by
makemigrations
) to the database. - It looks at the migration files and applies any unapplied migrations to the database, creating or altering database tables as necessary.
- This is the command that actually modifies the database structure.
Example:
python manage.py migrateThis applies the changes to the database, updating the schema as specified in the migration files.
- This command is used to apply the migrations (including those generated by
Workflow
- You typically first run
makemigrations
after changing your models to create the migration files. - Then, you run
migrate
to apply those migrations and update the database.
Tracking Model Changes?
makemigrations
in Django is incremental and generates migration files that depend on the latest changes to your models.
Here’s how it works:
-
Tracking Changes:
- When you run
makemigrations
, Django compares your current model definitions (in yourmodels.py
) to the last set of migration files that were applied to the database. - It looks for any changes you’ve made since the last migration, such as adding/removing/altering fields, changing models, etc.
- When you run
-
Generating Migration Files:
- Django then creates a new migration file that describes the changes made to your models (this includes adding new fields, creating new models, or altering existing ones).
- This migration file represents the changes that need to be applied to the database schema.
-
Incremental Process:
- Each migration file is applied in the order in which it was created. Django keeps track of the migrations that have been applied to the database, and only the new changes since the last migration will be reflected in the new migration file.
- If you’ve already applied previous migrations (e.g., by running
migrate
), Django will only create migration files for new changes to the models.
Example
Let’s say you have the following models in models.py
initially:
class Book(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=100)
-
First Migration: After running
makemigrations
andmigrate
the first time, Django will create a migration file that creates theBook
table with thetitle
andauthor
fields. -
Make a Change: Now, you modify your model by adding a new field
published_date
:# models.py (after change)class Book(models.Model):title = models.CharField(max_length=100)author = models.CharField(max_length=100)published_date = models.DateField(null=True) -
Second Migration: When you run
makemigrations
again, Django will detect the change (the addition of thepublished_date
field) and create a new migration file to add thepublished_date
field to theBook
table in the database. -
Applying the Migration: Finally, when you run
migrate
, Django will apply this new migration to update the database schema with the added field.
Incremental Nature of makemigrations
- Only New Changes Are Included: Django only generates migrations for changes made to the models since the last migration was created. It does not regenerate migrations for things that have already been applied to the database.
- Database State: The
makemigrations
command generates migration files that reflect the difference between the current state of your models and the state of your database based on the migrations that have already been applied.
This approach makes migrations incremental, and it ensures that your database schema is always updated to reflect the latest state of your models.
Rolling Back Migrations Using migrate
Command
You can roll back migrations by specifying the migration you want to revert to. Django will then apply the necessary steps to “undo” any migrations that were applied after that point.
Rollback to a Specific Migration:
You can use the migrate
command and specify a particular migration (or app) to revert to.
python manage.py migrate <app_name> <migration_name>
-
Example: To roll back to a migration named
0002_auto_20250306_1234
for an app calledmyapp
, you would run:Terminal window python manage.py migrate myapp 0002_auto_20250306_1234This will undo all migrations that were applied after
0002_auto_20250306_1234
formyapp
.
Rolling Back All Migrations for an App:
If you want to undo all migrations for a particular app, you can migrate it back to the initial state (i.e., the state before any migrations were applied). To do this, specify zero
as the migration name:
python manage.py migrate <app_name> zero
-
Example: To rollback all migrations for
myapp
:Terminal window python manage.py migrate myapp zeroThis will undo all migrations for that app, essentially deleting all database changes made by those migrations.
Delete Migration Files
If you want to “erase” a migration that was created incorrectly or you simply want to start fresh, you can delete the migration file manually from the migrations
directory within the app.
Steps:
-
Go to the
migrations
directory of your app (e.g.,myapp/migrations
). -
Delete the migration file(s) you want to remove (e.g.,
0003_auto_20250306_1234.py
). -
After deleting the migration files, run the
migrate
command again to ensure the database schema is consistent with the remaining migrations.Terminal window python manage.py migrateWarning: Deleting migration files should be done carefully, especially on a shared or production database, as it may cause inconsistencies or errors.
Fake Migrations
Sometimes, you may need to mark migrations as applied or unapplied without actually applying or reverting the database changes. This is called “faking” a migration.
Fake Reverting Migrations:
If you’ve already applied a migration but want to pretend it wasn’t applied (without actually modifying the database), you can use the --fake
option:
python manage.py migrate <app_name> <migration_name> --fake
- Example: To fake revert to a previous migration (without rolling back changes in the database):
Terminal window python manage.py migrate myapp 0002_auto_20250306_1234 --fake
This tells Django that the migration has been applied, even if it hasn’t been (or you don’t want to apply it again).
Database Reset (for development)
If you are in a development environment and don’t mind losing all your data, you can reset the database entirely and start fresh. This is often the quickest way to undo migrations in a development environment, especially if you’re experimenting with migrations.
Steps:
-
Drop the database (or reset the schema).
-
Recreate the database.
-
Run
makemigrations
andmigrate
from scratch.Terminal window python manage.py migrate
Note: This approach is only recommended for development environments, as it will delete all your data.