# Django 5.2.8 ドキュメント

# マイグレーション・オペレーション

マイグレーションファイルは一つ以上の `オペレーション`、データベースに対してマイグレーションが行うべきオペレーションを宣言的に保持するオブジェクト、から構成されます。

Django はこれらの `Operation` オブジェクトも使用して、モデルの履歴を確認し、前回のマイグレーション以降にモデルに加えた変更を計算します。そのため、自動的にマイグレーションを書き出すことができます。マイグレーションの定義が宣言的なのはそのためであり、Django がそれらを簡単にメモリに読み込んで、データベースに触れることなくプロジェクトがどのようにあるべきかを把握するために実行することができます。

データのマイグレーション や高度なデータベースへの手動操作のような特別な `オペレーション` も存在します。もし頻繁に行われる独自の変更をカプセル化したければ独自に `オペレーション` を記述する事もできます。

もし独自の `Operation` オブジェクトを定義する空のマイグレーションファイルが必要であれば、`python manage.py makemigrations --empty yourappname` を実行してください。ただし、手動でのスキーマ変更オペレーションの追加はマイグレーションの自動検出機構を混乱させ、 `makemigrations` が正しい結果を出力しなくなる可能性があることに十分注意してください。

Django が提供するコア機能は全て `django.db.migrations.operations` モジュールから利用できます。

より入門的な内容に関しては、 トピックスのマイグレーション を参照ください。

## スキーマ・オペレーション

### `CreateModel`

class CreateModel(name, fields, options=None, bases=None, managers=None)

プロジェクトの履歴に新たなモデル、そしてデータベース上に対応するテーブルを作成します。

`name` は `models.py` ファイルに定義されているであろうモデルの名称です。

`fields` は `(フィールド名, フィールドのインスタンス)` という 2 値のタプルのリストです。フィールドのインスタンスは束縛されないフィールド(他のモデルから取得した物でなく、単に `models.CharField(...)` 等と記述する物)でなければいけません。

`options` は定義されるモデルの `Meta` クラスの値からなるオプションの辞書オブジェクトです。

`bases` はオプションで、このモデルに継承させる他のクラスのリストです。（すでに定義した他のモデルを継承する場合、）クラスオブジェクトまたは `"appname.ModelName"` という形式の文字列を含めることができます。このパラメータが空の場合、デフォルトでは標準の `models.Model` から継承します。

`managers` は `(マネージャ名, マネージャのインスタンス)` という 2 値のタプルのリストを受け取ります。マイグレーションの間はリスト内で最初に定義されたマネージャがこのモデルの標準マネージャとして利用されます。

### `DeleteModel`

class DeleteModel(name)

プロジェクトの履歴からモデルを、加えてデータベースから該当モデルを扱うテーブルを削除します。

### `RenameModel`

class RenameModel(old_name, new_name)

モデルの名称を今までの名称から新しい名称に変更します。

一度に定義しているモデルの名前とかなり多くのフィールドの名前を変更した場合は手動でこの処理を追加する必要があるかもしれません;マイグレーションの自動検知機構が古い名称を持ったモデルを削除して異なった名称のモデルを追加したと認識してしまうため、そのマイグレーション処理は古いテーブルの全てのデータを消去してしまいます。

### `AlterModelTable`

class AlterModelTable(name, table)

定義しているモデルのテーブル名を変更します(`Meta` サブクラスの `db_table` オプションを参照します)。

### `AlterModelTableComment`

class AlterModelTableComment(name, table_comment)

モデルのテーブルコメント (`Meta` サブクラスの `db_table_comment` オプション) を変更します。

### `AlterUniqueTogether`

class AlterUniqueTogether(name, unique_together)

モデルのユニーク制約のセットを変更します (`Meta` サブクラスの `unique_together` オプション)。

### `AlterIndexTogether`

class AlterIndexTogether(name, index_together)

モデルのカスタムインデックスのセットを変更します (`Meta` サブクラスの `index_together` オプション)。

警告

`AlterIndexTogether` は公式には Django 4.2 以前のマイグレーションファイルにのみサポートされています。後方互換性の理由から、これはまだパブリック API の一部であり、非推奨または削除する予定はありませんが、新しいマイグレーションには使わないでください。代わりに `AddIndex` と `RemoveIndex` オペレーションを使ってください。

### `AlterOrderWithRespectTo`

class AlterOrderWithRespectTo(name, order_with_respect_to)

`Meta` サブクラスの `order_with_respect_to` オプションに必要な `_order` カラムを作成または削除します。

### `AlterModelOptions`

class AlterModelOptions(name, options)

`permissions` や `verbose_name` のような雑多なモデルオプション（モデルの `Meta` の設定）の変更を保存します。データベースには影響を与えませんが、 `RunPython` インスタンスが使用するためにこれらの変更を保持します。 `options` はオプション名と値をマッピングした辞書である必要があります。

### `AlterModelManagers`

class AlterModelManagers(name, managers)

マイグレーション中に利用可能なマネージャを変更します。

### `AddField`

class AddField(model_name, name, field, preserve_default=True)

モデルにフィールドを追加します。 `model_name` はモデル名、 `name` はフィールド名、 `field` はバインドされていないフィールドのインスタンスです。これは `models.py` のフィールド宣言に記述します。たとえば、 `models.IntegerField(null=True)` のように書きます。

引数 `preserve_default` は、フィールドのデフォルト値が永続的で、プロジェクトの状態に焼き込むべきもの (`True`) か、それとも一時的で今回のマイグレーションのためのもの (`False`) かを示します。通常、マイグレーションはテーブルに NULL 値でないフィールドを追加するため、既存の行に入れるデフォルト値が必要なためです。Django がデータベースのデフォルトを設定することはなく、常に Django ORM コードの中でデフォルトを適用します。これは、データベースにデフォルトを直接設定する動作には影響しません。

警告

古いデータベースでは、デフォルト値を持つフィールドを追加すると、テーブルの完全な書き換えが発生することがあります。これはNULL可能なフィールドでも発生し、パフォーマンスに悪影響を及ぼす可能性があります。これを避けるには、以下の手順を実行する必要があります。

- デフォルト値なしで nullable フィールドを追加し、 `makemigrations` コマンドを実行します。これで `AddField` オペレーションを持つマイグレーションが生成されるはずです。

- デフォルト値をフィールドに追加し、 `makemigrations` コマンドを実行します。これで `AlterField` オペレーションを持つマイグレーションが生成されるはずです。

### `RemoveField`

class RemoveField(model_name, name)

モデルからフィールドを削除します。

逆の場合、これは実際にはモデルにフィールドを追加していることに留意してください。フィールドが null 許容であるか、再作成されたカラムに入力するために使われるデフォルト値を持っている場合、この操作は可逆です（データの損失を除けば不可逆です）。フィールドが null 許容でなく、デフォルト値を持たない場合、この操作は不可逆です。

Changed in Django 6.0:

`BaseDatabaseSchemaEditor` and PostgreSQL backends no longer use `CASCADE` to delete dependent related database objects, such as views. Any dependent objects that are not managed by Django may need to be removed manually before running `RemoveField`.

### `AlterField`

class AlterField(model_name, name, field, preserve_default=True)

フィールドの型を変更したり、 `null`, `unique`, `db_column` などのフィールド属性を変更したりします。

引数 `preserve_default` は、フィールドのデフォルト値が永続的で、プロジェクトの状態に保持されるべきもの (`True`) か、それとも一時的でこのマイグレーションのためだけのもの (`False`) かを指定します。通常マイグレーションは null 許容のフィールドを null 非許容のフィールドに変更し、既存の行に入れるデフォルト値が必要だからです。Django がデータベースのデフォルトを設定することはなく、常に Django ORM コードの中でデフォルトを適用します。

たとえば、 `models.TextField()` のようなテキスト型のフィールドを `models.IntegerField()` のような数値型のフィールドに変更することは、ほとんどのデータベースではできません。

### `RenameField`

class RenameField(model_name, old_name, new_name)

フィールドの名前を変更します(また、 `db_column` が指定されていない限り、カラム名も変更します)。

### `AddIndex`

class AddIndex(model_name, index)

データベーステーブルに `model_name` のモデルのインデックスを作成します。 `index` は `Index` クラスのインスタンスです。

### `RemoveIndex`

class RemoveIndex(model_name, name)

`model_name` のモデルから `name` という名前のインデックスを削除します。

### `RenameIndex`

class RenameIndex(model_name, new_name, old_name=None, old_fields=None)

モデルの `model_name` に対するデータベーステーブルのインデックスの名前を変更します。 `old_name` と `old_fields` のいずれか一方のみを提供できます。 `old_fields` は文字列のイテラブルで、通常は `index_together` （Django 5.1以前のオプション）のフィールドに対応します。

On databases that don't support an index renaming statement (SQLite), the operation will drop and recreate the index, which can be expensive.

### `AddConstraint`

class AddConstraint(model_name, constraint)

データベーステーブルの `model_name` のモデルに 制約 を作成します。

### `RemoveConstraint`

class RemoveConstraint(model_name, name)

`model_name` のモデルから `name` という名前の制約を削除します。

### `AlterConstraint`

New in Django 5.2.

class AlterConstraint(model_name, name, constraint)

データベースに影響を与えることなく、`model_name` で指定したモデルの `name` という名前の制約を新たな `constraint` に置き換えます。

## 特別なオペレーション

### `RunSQL`

class RunSQL(sql, reverse_sql=None, state_operations=None, hints=None, elidable=False)

データベース上で任意の SQL を実行できるようにします。Django が直接サポートしていない、データベースバックエンドのより高度な機能に便利です。

`sql` と `reverse_sql` があれば、データベースで実行する SQL の文字列を指定します。ほとんどのデータベースバックエンド (PostgreSQL 以外) では、 Django は SQL を実行する前に個々の文に分割します。

警告

PostgreSQL と SQLite では、Django のトランザクション状態を壊さないように、 ノンアトミックなマイグレーション の SQL で `BEGIN` か `COMMIT` だけを使ってください。

文字列もしくは 2 値のタプルのリストを渡すことができます。その内後者はクエリとパラメータを cursor.execute() において行うのと同じ形式で渡すために用いられます。以下の 3 つの処理は互いに等価です:

    migrations.RunSQL("INSERT INTO musician (name) VALUES ('Reinhardt');")
    migrations.RunSQL([("INSERT INTO musician (name) VALUES ('Reinhardt');", None)])
    migrations.RunSQL([("INSERT INTO musician (name) VALUES (%s);", ["Reinhardt"])])

クエリにパーセント文字リテラルを含ませたい場合、パラメータを渡していればパーセント文字を二重に記述する必要があります。

`reverse_sql` クエリはマイグレーションを元に戻す際に実行されます。これらのクエリは `sql` クエリで実行された内容を元に戻します。たとえば、上記の挿入を削除で取り消す場合:

    migrations.RunSQL(
        sql=[("INSERT INTO musician (name) VALUES (%s);", ["Reinhardt"])],
        reverse_sql=[("DELETE FROM musician where name=%s;", ["Reinhardt"])],
    )

`reverse_sql` が `None` (デフォルト) の場合、 `RunSQL` オペレーションは元に戻りません。

引数 `state_operations` にはプロジェクトのステートから見た SQL と等価となる処理を渡すことができます。たとえば、手動でカラムを作成した場合、マイグレーションの自動検知機構が最新のモデルのステートを保持できるように `AddField` のリストを渡す必要があります。そうしなければ、次に `makemigrations` を実行した際、フィールドを追加した処理を一切検知せずに同じ追加処理を再度適用してしまうでしょう。次に例を示します。

    migrations.RunSQL(
        "ALTER TABLE musician ADD COLUMN name varchar(255) NOT NULL;",
        state_operations=[
            migrations.AddField(
                "musician",
                "name",
                models.CharField(max_length=255),
            ),
        ],
    )

オプションの `hints` 引数はデータベースルータオブジェクトの `allow_migrate()` メソッドに `**hints` として渡されてルーティングの決定を補助します。データベースのヒントに関しての詳細は ヒント を参照ください。

オプションの `elidable` 引数はこの処理を マイグレーションのスカッシュ を行った際に消去する(省略する)か否かを決定します。

RunSQL.noop

  指定された順序での処理を行わない場合、`sql` もしくは `reverse_sql` に対して `RunSQL.noop` 要素を渡します。これは特に処理を逆の順序で行いたい場合に有用です。

### `RunPython`

class RunPython(code, reverse_code=None, atomic=None, hints=None, elidable=False)

マイグレーション履歴を反映して独自の Python コードを実行します。`code` (与えられれば加えて `reverse_code` )は二つの引数を受け取る呼び出し可能オブジェクトでなければなりません;第一引数はプロジェクトの履歴において処理の場所が一致している履歴を反映したモデルを含んだ `django.apps.registry.Apps` のインスタンスであり、第二引数は `SchemaEditor` のインスタンスです。

`reverse_code` 引数はマイグレーションを元に戻す際に呼び出されます。この呼び出し可能オブジェクトはマイグレーションが逆順処理可能となるよう、先の呼び出し可能オブジェクト `code` で行われた処理を無効化しなければなりません。 `reverse_code` が `None` (デフォルト) の場合、 `RunPython` オペレーションは元に戻りません。

オプションの `hints` 引数はルーティングの決定を補助するためにデータベースルータの `allow_migrate()` メソッドに `**hints` として渡されます。データベースのヒントに関しての詳細は ヒント を参照してください。

オプションの `elidable` 引数はこの処理を マイグレーションのスカッシュ を行った際に消去する(省略する)か否かを決定します。

マイグレーションファイルの `Migration` クラスから独立した別の関数として記述し、 `RunPython` に渡すことを推奨します。以下に `RunPython` を用いて `Country` モデル上の初期オブジェクトを追加する例を示します:

    from django.db import migrations

    def forwards_func(apps, schema_editor):
        # We get the model from the versioned app registry;
        # if we directly import it, it'll be the wrong version
        Country = apps.get_model("myapp", "Country")
        db_alias = schema_editor.connection.alias
        Country.objects.using(db_alias).bulk_create(
            [
                Country(name="USA", code="us"),
                Country(name="France", code="fr"),
            ]
        )

    def reverse_func(apps, schema_editor):
        # forwards_func() creates two Country instances,
        # so reverse_func() should delete them.
        Country = apps.get_model("myapp", "Country")
        db_alias = schema_editor.connection.alias
        Country.objects.using(db_alias).filter(name="USA", code="us").delete()
        Country.objects.using(db_alias).filter(name="France", code="fr").delete()

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

        operations = [
            migrations.RunPython(forwards_func, reverse_func),
        ]

これは データのマイグレーション の作成、独自のデータ更新と構成変更、そして ORM や Python のコードにアクセスを必要とするあらゆるオペレーションのために行われる一般的なオペレーションです。

`RunSQL` と同様、もし内部のスキーマを変更する場合は Django のモデル機構のスコープ範囲外 (たとえば triggers など) で行うか、もしくはモデルの状態に変更を反映する処理に `SeparateDatabaseAndState` を追加する事を心がけてください。そうでなければ、バージョン管理された ORM およびマイグレーションの自動検出機構が正常に動作しなくなってしまいます。

標準では `RunPython` は DDL トランザクションをサポートしないデータベース (たとえば MySQL と Oracle など) 上では通常のトランザクション内で記述された内容の処理を行います。この仕組みは安全ではありますが、これらのデータベースバックエンドを利用中に `schema_editor` を利用しようとするとクラッシュを引き起こす場合があります。このような場合は、`RunPython` に対して `atomic=False` を渡してください。

トランザクション中の DDL 使用をサポートしているデータベース(SQLite や PostgreSQL)においては、`RunPython` は各マイグレーションに対して作成されたトランザクション以外に自動的にトランザクションを保持しません。そのため、たとえば PostgreSQL では、スキーマ変更と `RunPython` を同一のマイグレーション内で結合させて用いるのは避けるべきであり、そうしなければ `OperationalError: cannot ALTER TABLE "mytable" because it has pending trigger events` のようなエラーに遭遇する可能性があります。

もしここまでに挙げられた物と異なるデータベースを利用しておりトランザクション中の DDL 事項をサポートしているか不明な場合、 `django.db.connection.features.can_rollback_ddl` 属性を確認してください。

もし `RunPython` オペレーションが 非アトミックなマイグレーション の一部である場合、そのオペレーションは `RunPython` オペレーションに対して `atomic=True` が渡されて生成されたトランザクション中においてのみ実行されます。

警告

`RunPython` はモデルのデータベース接続を魔法のように切り替える事はしません;データベースのエイリアス(作成した関数の第二引数 `schema_editor` 内、 `schema_editor.connection.alias` から利用可能)を指定していないモデルのメソッドはすべてデフォルトのデータベースを利用します。

static RunPython.noop()

  指定された順序で処理を行いたくない場合は `code` もしくは `reverse_code` に `RunPython.noop` メソッドを渡してください。この指定は処理を逆順で行いたい場合に特に有用です。

### `SeparateDatabaseAndState`

class SeparateDatabaseAndState(database_operations=None, state_operations=None)

データベース(スキーマ変更)と状態(自動検出機能)という2つの側面を混在させてマッチさせることができる、高度に専門化されたオペレーションです。

これは2つのオペレーションのリストを受け入れます。状態への適用を求められたときは、 `state_operations` リストを使用します(これは `RunSQL` の `state_operations` 引数の一般化されたバージョンです)。データベースへの変更の適用を求められたときは、 `database_operations` リストを使用します。

データベースの実際の状態と Django の状態のビューが同期しなくなると、マイグレーションフレームワークが壊れてしまい、データが失われることさえあります。じっくりと、データベースと状態のオペレーションを慎重にチェックすべきです。データベースのオペレーションをチェックするために、 `sqlmigrate` と `dbshell` を使うことができます。状態のオペレーションをチェックするために `makemigrations` 、特に `--dry-run` を使うことができます。

`SeparateDatabaseAndState` の使用例は、 ManyToManyField を中間 (through) モデルを使うように変更する を参照してください。

## オペレーション・カテゴリ

class OperationCategory

  `makemigrations` コマンドで意味のある記号を表示するために使用される、マイグレーションオペレーションのカテゴリ。

  ADDITION

    記号: `+`

  REMOVAL

    記号: `-`

  ALTERATION

    記号: `~`

  PYTHON

    記号: `p`

  SQL

    記号: `s`

  MIXED

    記号: `?`

## 独自のオペレーションを書く

オペレーションは比較的シンプルな API を持っており、Django に内蔵された機能を独自に補助する処理を簡単に記述できるよう設計されています。`Operation` の基本構造は以下のようなものです:

    from django.db.migrations.operations.base import Operation

    class MyCustomOperation(Operation):
        # If this is False, it means that this operation will be ignored by
        # sqlmigrate; if true, it will be run and the SQL collected for its output.
        reduces_to_sql = False

        # If this is False, Django will refuse to reverse past this operation.
        reversible = False

        # This categorizes the operation. The corresponding symbol will be
        # displayed by the makemigrations command.
        category = OperationCategory.ADDITION

        def __init__(self, arg1, arg2):
            # Operations are usually instantiated with arguments in migration
            # files. Store the values of them on self for later use.
            pass

        def state_forwards(self, app_label, state):
            # The Operation should take the 'state' parameter (an instance of
            # django.db.migrations.state.ProjectState) and mutate it to match
            # any schema changes that have occurred.
            pass

        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            # The Operation should use schema_editor to apply any changes it
            # wants to make to the database.
            pass

        def database_backwards(self, app_label, schema_editor, from_state, to_state):
            # If reversible is True, this is called when the operation is reversed.
            pass

        def describe(self):
            # This is used to describe what the operation does.
            return "Custom Operation"

        @property
        def migration_name_fragment(self):
            # Optional. A filename part suitable for automatically naming a
            # migration containing this operation, or None if not applicable.
            return "custom_operation_%s_%s" % (self.arg1, self.arg2)

上の例もテンプレートとして利用できますが、 `django.db.migrations.operations` 内の Django 組み込みのオペレーションを参考にすることをお勧めします。これらは `ProjectState` や履歴上のモデルを取得するために使用されるパターン、 `ModelState` や `state_forwards()` で履歴上のモデルを模倣するために使用されるパターンなど、マイグレーションフレームワークの半内部的な側面の使用例を多くカバーしています。

いくつかの注意すべき点

- マイグレーションを記述するのに `ProjectState` について多くを学ぶ必要はありません。ただし、それがアプリケーションの登録情報へのアクセスを提供するプロパティ `app` を持っていることだけは知っていて下さい。それに対して `get_model` を呼ぶことで取得できます。

- `database_forwards` と `database_backwards` はどちらもパラメータとして 2 つの状態を受け取ります。これらは `state_forwards` メソッドが適用するであろう差分を表していますが、利便性と実行速度のために渡されます。

- もし `database_forwards()` や `database_backwards()` の `from_state` 引数からモデルクラスやモデルインスタンスを操作したい場合は、 `clear_delayed_apps_cache()` メソッドを使ってモデルの状態をレンダリングし、リレーション先モデルを利用できるようにする必要があります:

      def database_forwards(self, app_label, schema_editor, from_state, to_state):
          # This operation should have access to all models. Ensure that all models are
          # reloaded in case any are delayed.
          from_state.clear_delayed_apps_cache()
          ...

- database_backwards メソッドにおける `to_state` は 古い 状態を示します;そのため、その値はマイグレーションが状態を戻した場合は現在の状態となります。

- 内蔵されたオペレーションにおいて `references_model` が実装されているのを見つけるかもしれません;これは独自のオペレーションのためでなく自動検知機構のコードの一部として存在しています。

警告

パフォーマンス上の理由から、`ModelState.fields` 内の `Field` のインスタンスはマイグレーション間で再利用されます。これらのインスタンスの属性を決して変更してはいけません。`state_forwards()` 内のフィールドを変更したい場合は、`ModelState.fields` から古いインスタンスを削除して新たなインスタンスと置き換える必要があります。`ModelState.managers` 内の `Manager` のインスタンスについても同様です。

簡単な例として、(PostgreSQL のよりエキサイティングな機能を含んだ) PostgreSQL 拡張をロードするオペレーションを作成してみましょう。これはモデルの状態を変えず、1 つのコマンドを実行します:

    from django.db.migrations.operations.base import Operation

    class LoadExtension(Operation):
        reversible = True

        def __init__(self, name):
            self.name = name

        def state_forwards(self, app_label, state):
            pass

        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            schema_editor.execute("CREATE EXTENSION IF NOT EXISTS %s" % self.name)

        def database_backwards(self, app_label, schema_editor, from_state, to_state):
            schema_editor.execute("DROP EXTENSION %s" % self.name)

        def describe(self):
            return "Creates extension %s" % self.name

        @property
        def migration_name_fragment(self):
            return "create_extension_%s" % self.name