概要(Django migration=「モデルの変更履歴を DB に安全に反映する仕組み」)
Django の migration(マイグレーション)は、一言でいうと、
「models.py の変更を、データベースに安全に反映するための“変更履歴”」
です。
モデルを書き換えるたびに、
自分で ALTER TABLE ... みたいな SQL を書くのは現実的ではありません。
そこで Django は、
モデルの変更を検知して
「こういう変更を DB に適用すべき」という“設計図ファイル(migration)”を作り
その設計図を順番に実行していくことで
DB の状態を、コードの状態に追いつかせる
という仕組みを用意しています。
ここから、
なぜ migration が必要なのか
基本コマンド(makemigrations / migrate)の意味
migration ファイルの中身のイメージ
よくある変更(フィールド追加・削除・リネームなど)の流れ
初心者がハマりやすいポイントと考え方
を、例を交えながらかみ砕いて説明していきます。
なぜ migration が必要なのかをイメージでつかむ
「models.py を変えただけでは DB は変わらない」
まず、ここが超重要です。
models.py を書き換えても、
その瞬間に DB のテーブルが勝手に変わるわけではありません。
例えば、最初にこういうモデルがあったとします。
class Book(models.Model):
title = models.CharField(max_length=200)
Pythonここから、あとで price フィールドを追加したくなったとします。
class Book(models.Model):
title = models.CharField(max_length=200)
price = models.IntegerField()
Pythonこの変更を保存しただけでは、
DB の book テーブルには price 列はまだ存在しません。
Django は、
「コード(models.py)の状態」と
「DB の実際の状態」
を一致させるために、
「migration」という“差分の履歴”を使います。
migration は「DB に対する git のようなもの」
イメージとしては、
models.py の変更
→ それを元に「migration ファイル(差分)」を作る
→ その migration を DB に適用する
という流れです。
git でいうと、
コードを変更する
→ git add して git commit する
→ 他の環境で git pull して反映する
に少し似ています。
migration ファイルは、
「この時点で、こういうテーブルを作った」
「このタイミングで、このフィールドを追加した」
「このときに、このフィールド名を変えた」
といった「DB の変更履歴」を Python コードとして持っています。
Django はこの履歴を見ながら、
まだ適用されていない migration を順番に実行して
DB を最新の状態に追いつかせる
という動きをします。
基本コマンド:makemigrations と migrate の役割
makemigrations=「モデルの変更から migration ファイルを生成する」
モデルを変更したあと、まず実行するのがこれです。
python manage.py makemigrations
Pythonこれを実行すると、Django は
前回の models.py の状態と
今の models.py の状態を比較して
「どんな差分があるか」を解析し、
その差分を表す migration ファイルを
各アプリの migrations ディレクトリに作成します。
例えば、Book モデルを新しく作ったときは、
こんな感じの migration ができます(ざっくりイメージ)。
# app/migrations/0001_initial.py
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="Book",
fields=[
("id", models.AutoField(primary_key=True, ...)),
("title", models.CharField(max_length=200)),
],
),
]
Pythonprice フィールドを追加したときは、
次のような migration ができます。
# app/migrations/0002_book_price.py
class Migration(migrations.Migration):
dependencies = [
("app", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="book",
name="price",
field=models.IntegerField(default=0),
),
]
Pythonここで大事なのは、
migration ファイルは「DB に対する操作のリスト」operations に「CreateModel」「AddField」などが並ぶ
という構造です。
migrate=「migration ファイルを実際に DB に適用する」
makemigrations で「設計図(migration ファイル)」を作ったら、
次はそれを DB に適用します。
python manage.py migrate
Pythonこれを実行すると、Django は
どの migration がまだ DB に適用されていないかを確認し
未適用のものを順番に実行していく
という動きをします。
初回の migrate では、
Django 標準アプリ(auth, admin など)のテーブル
自分のアプリの 0001_initial など
が一気に作られます。
2 回目以降の migrate では、
新しく作られた migration だけが適用されます。
つまり、
models.py を変えた
→ makemigrations で差分ファイルを作る
→ migrate で DB に反映する
という 2 ステップが、
Django でモデルを変更するときの基本パターンです。
よくある変更パターンと migration の流れ
新しいモデルを追加する
Book モデルを新規作成したとします。
class Book(models.Model):
title = models.CharField(max_length=200)
Python流れはこうです。
python manage.py makemigrations
python manage.py migrate
Python0001_initial.py のような migration が作られ、migrate で book テーブルが DB に作られます。
フィールドを追加する(default に注意)
Book に price フィールドを追加します。
class Book(models.Model):
title = models.CharField(max_length=200)
price = models.IntegerField()
Pythonこの状態で makemigrations を実行すると、
Django からこんなことを聞かれる場合があります。
「既存のレコードに対して、この新しいフィールドの値をどうする?」
(default を指定するか、手動で値を入れるか)
なぜかというと、
すでに DB にある Book の行には、
price 列がまだ存在しないからです。
そこで Django は、
新しい列を追加するときに
既存の行に入れる初期値(default)が必要かどうか
を確認してきます。
初心者向けの安全なやり方は、
モデル側で default を付けておくことです。
class Book(models.Model):
title = models.CharField(max_length=200)
price = models.IntegerField(default=0)
Pythonこうしてから makemigrations すると、
migration ファイルに default=0 が書き込まれ、
既存の行にも 0 が入るようになります。
フィールド名を変える(RenameField)
例えば、price を amount に名前変更したいとします。
class Book(models.Model):
title = models.CharField(max_length=200)
amount = models.IntegerField(default=0)
Pythonこの状態で makemigrations をすると、
Django は「price が消えて amount が増えた」と認識します。
ここで、
「本当は rename したいだけなのに、
削除+追加として扱われるとデータが消えるのでは?」
という問題が出てきます。
Django はある程度賢いので、
単純なリネームなら RenameField として
migration を作ってくれることもありますが、
うまくいかない場合もあります。
初心者のうちは、
フィールド名を変えるときは慎重に
必要なら migration ファイルを確認して、
本当に RenameField になっているかを見る
という癖をつけておくと安全です。
モデルを削除する(DeleteModel)
モデルを削除するときも同様です。
class Book(models.Model):
...
Pythonを消して makemigrations すると、DeleteModel の migration が作られます。
migrate を実行すると、
DB からそのテーブルが削除されます。
本番環境でこれをやると、
そのテーブルのデータが全部消えるので、
本当に不要なモデルかどうかをよく確認する必要があります。
migration ファイルの中身を「怖がらずにチラ見する」
operations を読むと「何が起きるか」が分かる
migration ファイルは Python なので、
開いて読めます。
例えば、フィールド追加の migration はこんな感じです。
class Migration(migrations.Migration):
dependencies = [
("app", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="book",
name="price",
field=models.IntegerField(default=0),
),
]
Pythonここから分かることは、
この migration は 0001_initial のあとに適用される
Book モデルに price フィールドを追加する
そのフィールドは IntegerField で default=0
ということです。
「この migration を適用したら DB に何が起きるか」を
ざっくりイメージできるようになると、
migration が一気に怖くなくなります。
dependencies で「どの順番で適用されるか」が決まる
dependencies は「この migration の前に適用されているべき migration」です。
Django は dependencies を辿りながら、
正しい順番で migration を適用していきます。
複数アプリにまたがる変更(外部キーなど)があるときは、
他アプリの migration が dependencies に入ることもあります。
初心者のうちは、
「dependencies は Django が勝手にいい感じに書いてくれる」
くらいの理解で十分ですが、
「migration には順番がある」
「途中の migration を飛ばして適用することはできない」
という感覚だけは持っておくとよいです。
初心者がハマりやすいポイントと考え方
「models.py を変えたら、必ず makemigrations → migrate」
一番多いミスは、
models.py を変えたのにmakemigrations と migrate を忘れていて、
「なんか反映されない」と悩むパターンです。
Django では、
モデル変更
→ makemigrations
→ migrate
がセットです。
開発のリズムとして、
モデルをいじったら、すぐこの 2 コマンドを叩く
という癖をつけてしまうのが一番楽です。
migration ファイルを「消してリセットしたくなる」気持ちとの付き合い方
開発中に、
migration がぐちゃぐちゃになってきた
何かおかしくなって、全部やり直したくなった
という瞬間が必ず来ます。
ローカル開発環境なら、
DB を丸ごと消す
migrations フォルダの中身を消す(__init__.py は残す)makemigrations → migrate で作り直す
という「リセット」も現実的です。
ただし、本番環境や他の人と共有している環境では、
勝手に migration を消すのは危険です。
チーム開発や本番運用を見据えるなら、
migration は「DB の歴史」なので、
基本的には消さずに積み上げていくもの
という意識を持っておくとよいです。
「DB の中身を直接いじる」と migration がズレる
DB クライアント(phpMyAdmin や GUI ツールなど)で
直接テーブル構造を変えてしまうと、
models.py と migration と DB の状態が
バラバラになってしまいます。
Django プロジェクトでは、
テーブル構造の変更は必ず models.py → migration 経由でやる
DB を直接いじるのは、基本的に「データの中身」だけ
というルールにしておくと、
後で苦しまずに済みます。
まとめ(Django migration は「モデルと DB をつなぐ安全な橋」)
Django migration を初心者目線で整理すると、こうなります。
models.py を変えただけでは DB は変わらない。モデルの変更を DB に反映するために、「migration ファイル(変更履歴)」を作り、それを順番に適用していく仕組みが migration。python manage.py makemigrations は「モデルの差分から migration ファイルを生成する」コマンド、python manage.py migrate は「未適用の migration を DB に実行する」コマンド。
新しいモデルの追加、フィールドの追加・削除・リネームなどは、すべて migration として記録される。migration ファイルの operations を読むと「DB に何が起きるか」が分かる。
開発の基本リズムは「モデルを変えたら makemigrations → migrate」。DB の構造変更は必ずこのルートで行い、直接 DB をいじって構造を変えないのが安全。
