はじめに
Djangoプロジェクトに途中参加した際や、チームでDBを共有した際に「マイグレーション不整合(依存関係)エラー」に悩まされることがあります。全リセットでやり直せれば楽ですが、チームで共有している場合は勝手に変更してコミットするわけにはいきません。
例えば、以下のようなときのための記事です。
- 共有DBのダンプをもらってリストアし、
python manage.py migrateを実行したらエラーが出た - チームメンバーが追加したマイグレーションファイルをpullして
migrateしたらエラーになった - 途中参加でDBとコードの状態が合わず、マイグレーションが進まなくなった
エラー内容
-
django.db.migrations.exceptions.InconsistentMigrationHistoryなどのエラーが発生 - 例:
Migration accounts.0002_initial is applied before its dependency booking.0032_auto_20250516_1301 on database 'default'.
(accountsアプリの[0002_initial]マイグレーションが、依存先であるbookingアプリの[0032_auto_20250516_1301]よりも先に適用されている)
原因
- DB側のマイグレーション履歴(django_migrationsテーブル)と、手元のマイグレーションファイルや適用状況が食い違っている(=履歴と実体がズレている)ため、Djangoが正しい状態を判断できない
目次
- エラー内容の確認
- 【ソースコード】マイグレーション適用状況の確認
- 【DB】マイグレーション履歴の確認・修正・再適用
- 最終確認
- 補足:Djangoマイグレーションの基礎知識
解決までの手順
【ソースコード側のマイグレーションファイルの適用状況】と【DB側のマイグレーション履歴】を確認して、不整合部分の履歴を削除・再適用していきます。
1. エラー内容の確認
マイグレーション不整合エラーが発生した場合、まずはエラーメッセージからどのアプリ・どのマイグレーションで不整合が発生しているか特定します。
- 例:
Migration accounts.0002_initial is applied before its dependency booking.0032_auto_20250516_1301 on database 'default'.
この例では「accountsアプリの[0002_initial]マイグレーションが、依存先であるbookingアプリの[0032_auto_20250516_1301]よりも先に適用されてしまっている」ことが原因でエラーになっています。
2. 【ソースコード】マイグレーション適用状況の確認
どのマイグレーションファイルが適用済み([X])か、未適用([ ])かを一覧で確認し、エラーで指摘されたマイグレーションや依存関係の状態を把握します。
python manage.py showmigrations
- 実行例:
accounts
[X] 0001_initial
[ ] 0002_initial
booking
[X] 0030_auto_20250501_1000
[X] 0031_auto_20250510_1200
[ ] 0032_auto_20250516_1301
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X]が付いているものが適用済み、[ ]は適用できなかったマイグレーションファイルです。
[0002_initial]と[0032_auto_20250516_1301]がうまく適用できていないことが分かります。
3. 【DB】マイグレーション履歴の確認・修正・再適用
以下の手順で履歴を確認・修正し、正しい順序で --fake を使ってマイグレーションを適用し直します。
1. マイグレーションの履歴を確認する
まず、DBのdjango_migrations テーブルで該当アプリのマイグレーション履歴を確認します。
django_migrations テーブルには「どのアプリのどのマイグレーションが、いつ適用されたか」が記録されています。
- MySQLの場合:
SELECT * FROM django_migrations WHERE app='accounts';
- 実行例:
| app | name | applied |
|----------|----------------|--------------------|
| accounts | 0001_initial | 2024-05-20 10:00:00 |
| accounts | 0002_initial | 2024-05-25 09:30:00 ←実は履歴だけ進んでいる!|
[0002_initial]について、showmigrationsで[X]が付いていないのに、django_migrations テーブルではすでに適用されたことになっています。これがまさに今回のエラーの原因ということです。
なので、この適用履歴を消してもう一度やり直すことで解消を目指します。
【DockerでMySQLを利用している場合】
Dockerコンテナ内のMySQLに接続してから、SQLを実行してください。docker-compose exec <mysqlコンテナ名> mysql -u <ユーザー名> -p<パスワード> <データベース名>
※ <ユーザー名> などは自分の環境に合わせて置き換えてください。
2. 該当履歴をDBから削除する
エラーで指摘されたマイグレーション(例:accounts.0002_initial)の履歴をDBから削除します。
- MySQLの場合:
DELETE FROM django_migrations WHERE app='accounts' AND name='0002_initial';
3. 依存先のマイグレーションを --fake で適用する
依存先のマイグレーション(例:booking.0032_auto_20250516_1301)を --fake で適用します。
python manage.py migrate booking 0032_auto_20250516_1301 --fake
4. 依存元のマイグレーションを --fake で再適用する
依存元のマイグレーション(例:accounts.0002_initial)を --fake で再適用します。
python manage.py migrate accounts 0002_initial --fake
4. 最終確認
全てのマイグレーションが正しく適用されているかを確認します。
python manage.py migrate
他にも同様のエラーが出た場合は全て解消するまで、同じように履歴を確認・削除し、依存関係の順に --fake で適用します。
何も適用されなくなれば整合性OKです。
念のため python manage.py showmigrations で全て[X]になっているか確認しましょう。
お疲れ様でした!
補足:Djangoマイグレーションの基礎知識
makemigrations とは?
-
makemigrationsは、models.pyの変更内容をもとに「マイグレーションファイル(DB変更手順)」を自動生成するコマンドです。
python manage.py makemigrations
これにより、DBスキーマ変更の履歴がコードとして管理できます。
migrate とは?
-
migrateは、マイグレーションファイルの内容を実際にDBに適用するコマンドです。
python manage.py migrate
テーブル作成・カラム追加など、DB構造が物理的に変更されます。
migrate --fake とは?
-
migrate --fakeは、DBのスキーマは変更せず、マイグレーション履歴(django_migrationsテーブル)だけ「適用済み」に進めるコマンドです。
python manage.py migrate --fake
すでにDBが最新状態だが履歴だけズレている場合や、不整合解消時に使います。
migrateとmigrate --fakeの使い分け
- 通常は
python manage.py migrateを使い、マイグレーションファイルの内容を実際にDBへ反映させます。 -
--fakeオプションは、DBのスキーマは既に最新だが、マイグレーション履歴だけズレている場合や、不整合を解消したい場合に使います。- 例: すでに手動でDB変更が反映されている、他環境からDBを引き継いだ、など。
-
--fakeを使うと、Djangoは「マイグレーションが適用された」と履歴だけ進めるため、
実際のDB構造とマイグレーション内容が一致していることを必ず確認してから使いましょう。 - 誤って
--fakeを使うと、DBと履歴がさらにズレてしまう危険があるので注意してください。
例えば、新しいモデルを追加したのに--fakeを使うと、本来DBに反映されるべき変更(テーブル追加)が実際には行われていないのに、「適用済み」と履歴だけが進んでしまいます。
django_migrationsテーブルとは?
- Djangoが「どのマイグレーションが適用済みか」を管理するためのDB内のテーブルです。
- 各マイグレーションの適用履歴(アプリ名・マイグレーション名・適用日時など)が記録されます。
- これにより、Djangoは「どこまで適用済みか」「何が未適用か」を正確に把握できます。