DjangoでApp単位のMigrationをRollbackについてまとめてみる

環境

  • Django: 2.2 ( 3.0 )

↓ 取り敢えず、MigrationとかAppについて振り返ってみます。

DjangoにおけるAppとは

Djangoを使っていると App という概念で プロジェクト内に複数のアプリケーションを作って開発をしていくと思います。

docs.djangoproject.com

プロジェクトとアプリケーション プロジェクトとアプリの違いは何でしょうか? アプリとは、ウェブログシステム、公的記録のデータベース、小規模な投票アプリなど、何かを行う Web アプリケーションです。プロジェクトは、特定のウェブサイトの構成とアプリのコレクションです。プロジェクトには複数のアプリを含めることができます。 アプリは複数のプロジェクトに存在できます

公式では プロジェクトとアプリケーションは 完全に親子関係である、みたいな感じで言及されています。

例えば user というアプリケーションを作る場合は 以下のような階層構造のディレクトリを切って( python manage.py startapp user とすれば自動的に )開発を進めます。

user/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

例えば、アプリケーションがDBを扱うのであれば、上記ディレクトリの中の models.py に Model を実装し、python manage.py makemigrations user などとコマンドを叩くと、Migration ファイルを作成することができます。

Migrationについて

作成

Migrationは ディレクトリの migrations/ ディレクトリの中に作成されていきます。

初回のMigrationは 一般的に 0001_initial.py などの名前で作成され、以降は {0001からインクリメント}_{マイグレーションの内容}.py という形式で作られます。

例えば、0001_initial.py を作成後に member テーブルだけを作る Migrationを作って python manage.py makemigrations user を叩くことで 0002_member.py というファイルをDjangoが作ってくれます。

member というファイル名についてですが、これはDjangoが自動的に定義してくれます。 複数のModelの定義の変更を一つのMigrationに入れると 0002_auto_20200930_1200 みたいな感じで 年月日_日時 でファイル名を作成しますが、 新しいテーブルを1個追加する等であれば、ファイル名にその追加されるテーブル名を含めてくれたりします。

かしこいですね。

適用

python manage.py migrate user 0001 とすることで データベースの状態を0001_***.py まで実行された状態にしてくれます。

想像しやすいとは思いますが、後ろを 0010 とするとで migrations/ ディレクトリ内の 0001 〜0010 までのMigrationファイルが適用された状態になります。

ちなみに後ろの数字を除いて python manage.py migrate user とすると、 最新のMigrationが適用された状態にしてくれます。

ちなみに、このどこまで実行されているのか、みたいなのは Djangoが接続しているデータベースの中に管理するテーブルがあってそこで管理されてたりします。

ロールバック

では、 ロールバックは どうするのでしょうか。 実は Djangoには python manage.py rollback 〜 みたいなコマンドはありません。 ここでも migrate を使います。

docs.djangoproject.com

公式サイトではこう記述されています。

Brings the database schema to a state where the named migration is applied, but no later migrations in the same app are applied.

和訳すると ...

データベース スキーマを、指定されたマイグレーションが適用され、同じアプリ内のそれ以降のマイグレーションは適用されない状態にします。

ということです。

例えば、0010 まで適用された状態から一個ロールバックしたい場合は python manage.py migrate user 0009 と 一個前の状態を指定すると、 Djangoは 「データベースを 0009 のMigrationまで適用された状態にして それ以降(つまり 0010 )のMigrationが適用されていない状態」 に変えてくれます。これが実質ロールバックになるわけです。

では、 0001 をロールバックするにはどうすれば良いのでしょうか?という話があります。 0001_initial.py は user の中で最初のMigrationファイルであり、 「それより前のもの」 はありません。

その場合は python manage.py migrate user zerozero というキーワードをつけることで user アプリケーションのMigration を全く適用されてない状態にすることができます。

まとめ

コマンド 効果
python manage.py user 0001 0001までMigrationを適用し、0002以降は適用していない状態にする
python manage.py user user アプリケーションのMigrationを最新まで全て適用する状態にする
python manage.py user zero user アプリケーションのMigrationを何も適用されていない状態にする