Djangoのマイグレーション（migrations）を初心者にもわかりやすく解説してみた



最近、現場でDjangoのマイグレーション（`migrations`）まわりで調べたりハマったりすることがあったので、備忘録も兼ねてまとめておきます。

初心者の方にもわかるように、できるだけ丁寧に書いています。「そもそもマイグレーションって何？」というところから、「全部のコマンド・機能一覧」「実際の使い方」「よくあるハマりどころ」までまとめました。

---

## ✅ マイグレーションって何？

簡単に言うと、

> Djangoの「モデル（models.py）」の変更を、データベースに反映するための仕組み

です。

例えば、`models.py` に新しいフィールドを追加したら、データベースのテーブルにもその列を追加しなきゃいけないですよね。それを自動的にやってくれるのが「マイグレーション」です。

---

## 🔧 よく使う基本コマンド

| コマンド | 説明 |
|----------|------|
| `python manage.py makemigrations` | モデルの変更を検出し、マイグレーションファイルを作成する |
| `python manage.py migrate` | マイグレーションファイルを元にデータベースを更新する |
| `python manage.py showmigrations` | マイグレーションの一覧と、どこまで適用済みかを表示する |
| `python manage.py sqlmigrate アプリ名 0001_initial` | そのマイグレーションで実行されるSQLを表示する（実行はしない） |
| `python manage.py squashmigrations アプリ名 0001 0005` | 複数のマイグレーションを1つにまとめる |
| `python manage.py makemigrations --empty アプリ名` | 空のマイグレーションファイルを作る（手書き用） |

---

## 🗂 マイグレーションファイルって何が書いてあるの？

`migrations/0001_initial.py` みたいなファイルができて、こんな感じのコードが入っています👇

```python
from django.db import migrations, models

class Migration(migrations.Migration):
    initial = True

    dependencies = []

    operations = [
        migrations.CreateModel(
            name='Post',
            fields=[
                ('id', models.AutoField(primary_key=True)),
                ('title', models.CharField(max_length=100)),
                ('body', models.TextField()),
            ],
        ),
    ]
```

つまり、「どんな変更を加えるか」が `operations` に順番に書かれてます。

---

## 📘 どんな操作ができるの？（すべて紹介）

### モデル・フィールド関連

| 操作名 | 内容 |
|--------|------|
| `CreateModel` | モデルを新しく作る |
| `DeleteModel` | モデルを削除する |
| `AddField` | フィールドを追加する |
| `RemoveField` | フィールドを削除する |
| `AlterField` | フィールドの属性（型、null可など）を変更する |
| `RenameField` | フィールド名を変更する |
| `RenameModel` | モデル名を変更する |

### データ操作系

| 操作名 | 内容 |
|--------|------|
| `RunPython` | 任意のPythonコードを実行する（データ移行に使う） |
| `RunSQL` | 任意のSQLを実行する（DDLやDMLもOK） |
| `SeparateDatabaseAndState` | DBとモデル定義の同期を一時的に切り離す |

---

## 🧠 `RunPython` の使い方（例：データの初期投入）

```python
from django.db import migrations

def seed_data(apps, schema_editor):
    Post = apps.get_model('blog', 'Post')
    Post.objects.create(title='Hello World', body='最初の記事です！')

class Migration(migrations.Migration):
    dependencies = []

    operations = [
        migrations.RunPython(seed_data),
    ]
```

※ 逆方向（ロールバック時）も書けます。`RunPython(forward, reverse)` の形。

---

## 🔙 マイグレーションの巻き戻し・再実行

### 特定のマイグレーションまで戻す：

```bash
python manage.py migrate blog 0001_initial
```

### 全部やり直したい：

```bash
python manage.py migrate blog zero
python manage.py migrate
```

---

## 💡 よくあるハマりポイントと対処法

| 症状 | 対処 |
|------|------|
| `makemigrations`しても何も起きない | モデルの変更が保存されてるか、対象のアプリが正しいか確認 |
| `migrate`でエラーになる | 依存関係や過去のマイグレーションに破損がないか確認 |
| モデルとDBが一致しない | `migrate アプリ名 zero` → `migrate` でやり直しも検討 |
| データ移行で import エラー | `apps.get_model()` を使って、マイグレーション時のモデルを取得する必要あり |

---

## 🧰 便利なTips

- `makemigrations --name add_title_to_post` のように名前を付けてマイグレーション作成できる
- `showmigrations` でどこまでマイグレーション済みか一目でわかる
- `sqlmigrate` を使えば、実行前にSQL文を確認できて安心
- `RunSQL` でインデックス追加や制約変更などの高度な操作も可能

---

## 📌 まとめ

Djangoのマイグレーションは、単なるデータベース更新ツールではなく、チーム開発・本番環境でも安心して運用できるように設計された強力な仕組みです。

最初は少しとっつきにくいですが、仕組みを理解して慣れてくると、むしろありがたさを感じる場面が増えてきます。

---

## 🙋‍♂️ ご意見・質問など大歓迎です！

この記事が誰かの助けになれば嬉しいです！