Skip to content

5. Database Migrations

In Django, makemigrations and migrate are two key management commands used for working with database schema changes.

  1. 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 the models.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 makemigrations

    This will create new migration files under the migrations folder of the corresponding app.

  2. 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 migrate

    This applies the changes to the database, updating the schema as specified in the migration files.

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:

  1. Tracking Changes:

    • When you run makemigrations, Django compares your current model definitions (in your models.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.
  2. 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.
  3. 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:

models.py
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
  1. First Migration: After running makemigrations and migrate the first time, Django will create a migration file that creates the Book table with the title and author fields.

  2. 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)
  3. Second Migration: When you run makemigrations again, Django will detect the change (the addition of the published_date field) and create a new migration file to add the published_date field to the Book table in the database.

  4. 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.

Terminal window
python manage.py migrate <app_name> <migration_name>
  • Example: To roll back to a migration named 0002_auto_20250306_1234 for an app called myapp, you would run:

    Terminal window
    python manage.py migrate myapp 0002_auto_20250306_1234

    This will undo all migrations that were applied after 0002_auto_20250306_1234 for myapp.

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:

Terminal window
python manage.py migrate <app_name> zero
  • Example: To rollback all migrations for myapp:

    Terminal window
    python manage.py migrate myapp zero

    This 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:

  1. Go to the migrations directory of your app (e.g., myapp/migrations).

  2. Delete the migration file(s) you want to remove (e.g., 0003_auto_20250306_1234.py).

  3. 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 migrate

    Warning: 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:

Terminal window
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:

  1. Drop the database (or reset the schema).

  2. Recreate the database.

  3. Run makemigrations and migrate from scratch.

    Terminal window
    python manage.py migrate

Note: This approach is only recommended for development environments, as it will delete all your data.