Migrations

Back

Loading concept...

Django Migrations: Your Database’s Time Machine 🚀


The Story of Migrations

Imagine you have a LEGO house. You built it yesterday. Today, you want to add a new room. But wait! You can’t just smash everything and rebuild. You need a plan — a step-by-step guide that says:

“Add 10 blue bricks here. Remove 2 red bricks there.”

Django Migrations are exactly that plan — but for your database!

Every time you change your models (the blueprint of your data), Django creates a migration file. This file tells the database exactly what changed and how to update itself — without losing any data.


🎯 Migrations Overview

What Are Migrations?

Think of migrations like diary entries for your database.

Day What Happened
Day 1 Created a User table
Day 2 Added email field to User
Day 3 Removed nickname field

Each entry (migration) remembers exactly what changed. If you ever need to go back in time, you can!

Why Do We Need Them?

Without migrations, you’d have to:

  • Manually write SQL commands
  • Hope you remember every change
  • Pray nothing breaks

With migrations:

  • Django tracks changes automatically
  • Changes are version-controlled
  • Your whole team stays in sync
graph TD A["You Change models.py"] --> B["Run makemigrations"] B --> C["Migration File Created"] C --> D["Run migrate"] D --> E["Database Updated!"]

The Migration Workflow

  1. Change your model (add/remove/modify fields)
  2. Create a migration with makemigrations
  3. Apply it with migrate

That’s it! Three simple steps.


🛠️ Migration Commands

Django gives you powerful commands. Let’s meet them!

1. makemigrations — The Detective

This command detects what changed in your models.

# You added this field to your model:
class Book(models.Model):
    title = models.CharField(max_length=200)
    pages = models.IntegerField()  # NEW!

Now run:

python manage.py makemigrations

Django says: “Aha! I see you added pages. Let me write that down!”

Output:

Migrations for 'library':
  0002_book_pages.py
    - Add field pages to book

2. migrate — The Builder

This command applies migrations to your database.

python manage.py migrate

Django now actually creates the new column in your database table.

3. showmigrations — The Historian

Want to see all migrations? This shows them!

python manage.py showmigrations

Output:

library
 [X] 0001_initial
 [X] 0002_book_pages
 [ ] 0003_book_author
  • [X] = Applied (done!)
  • [ ] = Not applied yet

4. sqlmigrate — The Translator

Want to see the actual SQL code? Peek inside!

python manage.py sqlmigrate library 0002

Output:

ALTER TABLE "library_book"
ADD COLUMN "pages" integer NOT NULL;

5. migrate --fake — The Pretender

Sometimes you need Django to mark a migration as done without actually running it.

python manage.py migrate library 0002 --fake

Use with caution! It’s like saying “Trust me, the database already has this.”

Command Quick Reference

Command What It Does
makemigrations Creates migration files
migrate Applies migrations
showmigrations Lists all migrations
sqlmigrate app 000X Shows SQL for a migration
migrate --fake Marks as done (no action)
migrate app zero Undoes ALL app migrations

📁 Migration Files and Operations

What’s Inside a Migration File?

Every migration file lives in yourapp/migrations/ folder.

Let’s peek inside 0002_book_pages.py:

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('library', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='book',
            name='pages',
            field=models.IntegerField(),
        ),
    ]

Breaking It Down

1. dependencies — What must run first

dependencies = [
    ('library', '0001_initial'),
]

This migration waits for 0001 to finish first.

2. operations — The actual changes

operations = [
    migrations.AddField(...),
]

This is the list of database operations.

Common Operations

graph TD A["Migration Operations"] --> B["CreateModel"] A --> C["DeleteModel"] A --> D["AddField"] A --> E["RemoveField"] A --> F["AlterField"] A --> G["RenameField"] A --> H["RenameModel"]
Operation What It Does
CreateModel Makes a new table
DeleteModel Removes a table
AddField Adds a column
RemoveField Removes a column
AlterField Changes a column
RenameField Renames a column
RenameModel Renames a table

Example: Adding a Field

migrations.AddField(
    model_name='book',
    name='author',
    field=models.CharField(
        max_length=100,
        default='Unknown'
    ),
)

Example: Removing a Field

migrations.RemoveField(
    model_name='book',
    name='old_field',
)

Example: Renaming a Field

migrations.RenameField(
    model_name='book',
    old_name='title',
    new_name='book_title',
)

🔄 Data Migrations

Sometimes you need to move data around, not just change structure. That’s where data migrations shine!

What Are Data Migrations?

Imagine you split a fullname field into first_name and last_name.

Structure migrations create the new fields. Data migrations move the names over!

Creating a Data Migration

python manage.py makemigrations --empty library

This creates a blank migration file for you to fill in.

The RunPython Operation

from django.db import migrations

def split_names(apps, schema_editor):
    User = apps.get_model('library', 'User')
    for user in User.objects.all():
        parts = user.fullname.split(' ')
        user.first_name = parts[0]
        user.last_name = parts[-1]
        user.save()

def reverse_names(apps, schema_editor):
    User = apps.get_model('library', 'User')
    for user in User.objects.all():
        user.fullname = f"{user.first_name} {user.last_name}"
        user.save()

class Migration(migrations.Migration):

    dependencies = [
        ('library', '0003_add_name_fields'),
    ]

    operations = [
        migrations.RunPython(
            split_names,
            reverse_names
        ),
    ]

Key Points About Data Migrations

1. Always use apps.get_model()

# CORRECT - gets the model at migration time
User = apps.get_model('library', 'User')

# WRONG - might have different fields now
from library.models import User

2. Write a reverse function

migrations.RunPython(forward, reverse)

If something goes wrong, Django can undo it!

3. Keep them small Data migrations can be slow. Process in batches if needed.

When to Use Data Migrations

Scenario Use Data Migration?
Split one field into two ✅ Yes
Combine two fields into one ✅ Yes
Set default values based on logic ✅ Yes
Just add a new field ❌ No
Just rename a field ❌ No

🎬 Real-World Example

Let’s walk through a complete scenario!

Step 1: Create Initial Model

# models.py
class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
python manage.py makemigrations
python manage.py migrate

Step 2: Add a New Field

# models.py (updated)
class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    published = models.BooleanField(default=False)
python manage.py makemigrations
python manage.py migrate

Step 3: Data Migration

Now set all existing articles as published:

python manage.py makemigrations --empty blog
# 0003_set_published.py
from django.db import migrations

def set_all_published(apps, schema_editor):
    Article = apps.get_model('blog', 'Article')
    Article.objects.all().update(published=True)

class Migration(migrations.Migration):
    dependencies = [
        ('blog', '0002_article_published'),
    ]
    operations = [
        migrations.RunPython(set_all_published),
    ]
python manage.py migrate

Done! All articles are now published.


💡 Pro Tips

Tip 1: Check Before You Migrate

python manage.py showmigrations
python manage.py sqlmigrate app 0002

Tip 2: Squash Old Migrations

Too many migration files? Combine them!

python manage.py squashmigrations app 0001 0005

Tip 3: Never Edit Applied Migrations

If a migration is already in production, create a new one instead!

Tip 4: Test Migrations Locally First

Always run migrate on a test database before production.


🏁 Summary

graph TD A["Change models.py"] --> B["makemigrations"] B --> C["Migration File Created"] C --> D["migrate"] D --> E["Database Updated"] F["Need Data Changes?"] --> G["makemigrations --empty"] G --> H["Add RunPython"] H --> D
Concept Remember
Migrations Diary entries for your database
makemigrations Detects changes, creates files
migrate Applies changes to database
Migration Files Python files with operations
Data Migrations Move/transform actual data

You Did It! 🎉

You now understand Django migrations like a pro!

Remember:

  1. Change your models
  2. Create migrations with makemigrations
  3. Apply them with migrate
  4. Use data migrations when you need to move data

Your database is no longer scary. It’s your time machine, and you control it!


Happy coding! 🚀

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.