2つのDjangoアプリ間でモデルを移動する方法(Django 1.7)


133

したがって、約1年前にプロジェクトを開始し、すべての新しい開発者と同様に、構造にあまり焦点を当てていませんでしたが、Djangoを使用すると、プロジェクトのレイアウト、主にモデルの構造が恐ろしいように見え始めました。

私は主に単一のアプリでモデルを保持しており、これらのモデルのほとんどは独自の個別のアプリにあるはずですが、これを解決して南に移動しましたが、外部キーなどの影響により、トリッキーで本当に難しいことがわかりました。

ただし、Django 1.7と移行サポートが組み込まれているため、これを行うためのより良い方法はありますか?


4
承認された回答を変更することを検討してください。
Babken Vardanyan 2017年

将来これに遭遇する人のために:Django 3.xここで、そしてrealpython.com/move-django-model/…で詳述されているアプローチが私にとってはうまくいきました。古いアプリのモデルと新しいアプリのモデルの間に複数の外部キーがありました。
pradeepcep

回答:


16

データが失われる可能性があるため、古い回答を削除しています。以下のようオザンが述べた、我々は、各アプリで2つの移行を作成することができます。この投稿の下のコメントは私の古い答えを参照しています。

1つ目のアプリからモデルを削除する最初の移行。

$ python manage.py makemigrations old_app --empty

移行ファイルを編集して、これらの操作を含めます。

class Migration(migrations.Migration):

    database_operations = [migrations.AlterModelTable('TheModel', 'newapp_themodel')]

    state_operations = [migrations.DeleteModel('TheModel')]

    operations = [
      migrations.SeparateDatabaseAndState(
        database_operations=database_operations,
        state_operations=state_operations)
    ]

最初の移行に依存し、2番目のアプリで新しいテーブルを作成する2番目の移行。モデルコードを2番目のアプリに移動した後

$ python manage.py makemigrations new_app 

移行ファイルを次のように編集します。

class Migration(migrations.Migration):

    dependencies = [
        ('old_app', 'above_migration')
    ]

    state_operations = [
        migrations.CreateModel(
            name='TheModel',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
            ],
            options={
                'db_table': 'newapp_themodel',
            },
            bases=(models.Model,),
        )
    ]

    operations = [
        migrations.SeparateDatabaseAndState(state_operations=state_operations)
    ]

私は既存のデータを持っていますが、失うことのできない多くのデータがあります。おそらくこれでそれを行うことですか?
サムバッキンガム

@KevinChristopherHenryコードを変更しました。これにより、既存のデータが保持されます。
ChillarAnand 14

@SamBuckinghamはい、変更されたコードを使用して、データを失うことなく移行できます。
ChillarAnand 14

2
それが本当に最善の方法になると思います。素晴らしいものでしたすべての助けてくれてありがとう。
サムバッキンガム

1
IMOこれは間違ったソリューションです。移行の基本的な前提は、実行./manage.py migrateするとすべてが正常な状態で終了することです。手動でマイグレーションを偽装することは、IMOを間違った方法で行うことです。
jb。

341

これは、を使用してかなり簡単に行うことができますmigrations.SeparateDatabaseAndState。基本的に、データベース操作を使用して2つの状態操作と同時にテーブルの名前を変更し、1つのアプリの履歴からモデルを削除して別のアプリの履歴に作成します。

古いアプリから削除

python manage.py makemigrations old_app --empty

移行中:

class Migration(migrations.Migration):

    dependencies = []

    database_operations = [
        migrations.AlterModelTable('TheModel', 'newapp_themodel')
    ]

    state_operations = [
        migrations.DeleteModel('TheModel')
    ]

    operations = [
        migrations.SeparateDatabaseAndState(
            database_operations=database_operations,
            state_operations=state_operations)
    ]

新しいアプリに追加

まず、モデルを新しいアプリのmodel.pyにコピーしてから、次のようにします。

python manage.py makemigrations new_app

これにより、単純なCreateModel操作を唯一の操作とする移行が生成されます。SeparateDatabaseAndStateテーブルを再作成しようとしないような操作でそれをラップします。また、依存関係として以前の移行を含めます。

class Migration(migrations.Migration):

    dependencies = [
        ('old_app', 'above_migration')
    ]

    state_operations = [
        migrations.CreateModel(
            name='TheModel',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
            ],
            options={
                'db_table': 'newapp_themodel',
            },
            bases=(models.Model,),
        )
    ]

    operations = [
        migrations.SeparateDatabaseAndState(state_operations=state_operations)
    ]

14
本当に良い説明。これが答えになるはずです。テーブルの名前を変更すると、データの損失を回避できます。
Remiz、2014年

11
これはそれを行うための最良の方法であり、私のものよりはるかに優れています。回答の上部にメモを追加しました。
ChillarAnand 2014年

4
私はこれを行いましたが、この後にnewappで "makemigrations"を実行すると、名前をNoneに変更するAlterModelTable移行が生成されます。
ディエゴポンチャーノ2015年

4
これらの指示に基づいて私の問題を解決する方法を見つけました。必須フィールドである外部キー参照がある場合、問題はさらに複雑になります。参照を移動するためにいくつかのステップを追加する必要がありました。
Nostalg.io 2015

14
複数のリクエストがあったため、GitHubの例を使用して、FKモデルの移行に関する詳細な回答を作成しました。stackoverflow.com/questions/30601107/...
Nostalg.io

26

同じ問題が発生しました。 オザンの答えは私を大いに助けましたが、残念ながら十分ではありませんでした。確かに、移動したいモデルにリンクするいくつかのForeignKeyがありました。いくつかの頭痛の後、私は解決策を見つけたので、人々の時間を解決するためにそれを投稿することにしました。

さらに2つの手順が必要です。

  1. 何かを行う前に、すべてのForeignKeyリンクをTheModelに変更しますIntegerfield。次に実行しますpython manage.py makemigrations
  2. Ozanの手順を実行した後、外部キーを再変換します。のForeignKey(TheModel)代わりに元に戻しますIntegerField()。次に、もう一度移行します(python manage.py makemigrations)。これで移行でき、正常に機能するはずです(python manage.py migrate

それが役に立てば幸い。もちろん、悪いサプライズを避けるために、本番環境で試す前にローカルでテストしてください:)


8
ManyToManyField関係はどうですか?
tomcounsell 2015年

1
@tomcounsellのすばらしいコメント、移行の目的でのみ特定のthroughモデルを追加することで想定します。データをそのままにするために必要な多大な作業...
Wtower

多対多の関係は通常、2つの外部キーを持つテーブルにすぎないため、SQLの観点からは、この答えのトリックを適用できます。しかし、これをDjango経由でのみ実現するために、私が考えることができる1つのアプローチは、@ ozanの回答に沿ったものですが、最初のステップは、MTM関係に関係するテーブルを複製することです(各アプリのdupeの1つのバージョン)。 、すべての外部キーを新しいアプリに移行してから、古いアプリの複製を削除します。免責事項:私はテストしていません:)
Arnaud P

15

私のやり方(Django == 1.8、postgresでテスト済み、おそらく1.7でもテスト済み)

状況

app1.YourModel

しかし、あなたはそれをに行きたい: app2.YourModel

  1. YourModel(コード)をapp1からapp2にコピーします。
  2. これをapp2.YourModelに追加します。

    Class Meta:
        db_table = 'app1_yourmodel'
  3. $ python manage.py makemigrations app2

  4. 新しい移行(例:0009_auto_something.py)は、migrations.CreateModel()ステートメントを使用してapp2で作成されます。このステートメントをapp2の初期移行(例:0001_initial.py)に移動します(これまでと同じように動作します)。そして作成されたマイグレーションを削除します= 0009_auto_something.py

  5. app2.YourModelが常に存在するように、行動するのと同じように、移行からapp1.YourModelの存在を削除します。意味:CreateModelステートメントと、その後に使用したすべての調整またはデータ移行をコメント化します。

  6. そしてもちろん、プロジェクトを通じてapp1.YourModelへのすべての参照をapp2.YourModelに変更する必要があります。また、マイグレーションのapp1.YourModelへの可能なすべての外部キーをapp2.YourModelに変更する必要があることを忘れないでください。

  7. $ python manage.py migrateを実行しても、何も変更されていません。また、$ python manage.py makemigrationsを実行しても、新しいものは何も検出されていません。

  8. 最後の仕上げ:app2.YourModelからクラスメタを削除し、$ python manage.py makemigrations app2 && python manage.py migrate app2を実行します(この移行を確認すると、次のようなものが表示されます:)

        migrations.AlterModelTable(
        name='yourmodel',
        table=None,
    ),

table = Noneは、デフォルトのテーブル名(この場合はapp2_yourmodel)を取ることを意味します。

  1. 完了、データが保存されました。

PSは移行中に、content_type app1.yourmodelが削除され、削除できることがわかります。あなたはそれに対してイエスと言うことができますが、それを使用しない場合に限られます。そのコンテンツタイプへのFKをそのままにしておくことに大きく依存している場合は、はいまたはいいえにはまだ答えないでください。ただし、手動でその時点のデータベースにアクセスし、contentype app2.yourmodelを削除して、contenttype app1の名前を変更してください。 yourmodelをapp2.yourmodelに変更し、noと答えて続行します。


3
このソリューションは確かに@ozanよりも「ハッカー的」であり、間違いなくより多くの編集が必要ですが、私にとってはうまくいきました(そして、マイグレーションを編集しても問題ありません-文書によると、編集可能であるはずです)。
pgcd

1
おそらくapp_label = 'app1'metaオプションも使用します。
Wtower 2017年

天才!これは、ForeignKeyの関係で私にとって非常に役立ちました。これは、ManyToManyフィールドでも同様に機能すると思います。
Babken Vardanyan 2017年

私はあなたの手順に従いましたが、app1に属する一部のモデルのフィールドは、移動するモデル(myModel)への再帰的な関係を持つ外部キーで構成されています。field1 = models.ForeignKey('app1.myModel').移行するときと同様に、ValueErrorがそれを示すfield1 was declared with a lazy reference to 'app1.myModel' but app 'app1' doesn't provide model 'MyModel'
Deesha

12

Ozanの回答で要求されているように)緊張したハンドコーディングの移行が行われるため、以下はOzanとMichaelの戦略を組み合わせて、必要なハンドコーディングの量を最小限に抑えています。

  1. モデルを移動する前に、を実行して、クリーンなベースラインで作業していることを確認してくださいmakemigrations
  2. モデルのコードをからapp1に移動しますapp2
  3. @Michaelによって推奨されているようdb_tableに、「新しい」モデルのMetaオプションを使用して、古いデータベーステーブルを新しいモデルにポイントします。

    class Meta:
        db_table = 'app1_yourmodel'
  4. を実行しますmakemigrations。これは、生成されますCreateModelapp2してDeleteModelapp1。技術的には、これらの移行はまったく同じテーブルを参照し、テーブルを削除(すべてのデータを含む)して再作成します。

  5. 実際には、テーブルに対して何もしたくありません(または必要としません)。変更が行われたと信じるには、Djangoが必要です。@Ozanの答えに従って、state_operationsフラグSeparateDatabaseAndStateはこれを行います。そのため、両方の移行ファイルのすべてのmigrationsエントリをでラップします。例えば、SeparateDatabaseAndState(state_operations=[...])

    operations = [
        ...
        migrations.DeleteModel(
            name='YourModel',
        ),
        ...
    ]

    なる

    operations = [
        migrations.SeparateDatabaseAndState(state_operations=[
            ...
            migrations.DeleteModel(
                name='YourModel',
            ),
            ...
        ])
    ]
  6. また、新しい「仮想」CreateModel移行が、元のテーブル実際に作成または変更した移行に依存していることを確認する必要もあります。たとえば、新しい移行がapp2.migrations.0004_auto_<date>Create)とapp1.migrations.0007_auto_<date>Delete)の場合、最も簡単な方法は次のとおりです。

    • 依存関係を開いapp1.migrations.0007_auto_<date>てコピーしapp1ます(例:) ('app1', '0006...'),。これはの「直前」の移行でapp1あり、実際のすべてのモデル構築ロジックへの依存関係を含める必要があります。
    • 開いて app2.migrations.0004_auto_<date>、コピーした依存関係をdependenciesリストに追加します。

ForeignKey移動するモデルと関係がある場合、上記は機能しない可能性があります。これは次の理由で発生します:

  • 依存関係を自動的に作成されませんForeignKey変更
  • ForeignKey変更をラップしたくないstate_operationsので、変更がテーブル操作から分離されていることを確認する必要があります。

注:Django 2.2 models.E028はこのメソッドを壊す警告()を追加しました。あなたはそれを回避することができるかもしれmanaged=Falseませんが、私はそれをテストしていません。

「最小」の操作セットは状況によって異なりますが、次の手順はほとんどまたはすべてのForeignKey移行で機能します。

  1. モデルをapp1からapp2、セットdb_tableコピーしますが、FK参照は変更しないでください。
  2. makemigrationsすべてのapp2移行を実行してラップしますstate_operations(上記を参照)
    • 上記のようapp2 CreateTableに、最新のapp1移行に依存関係を追加します
  3. すべてのFK参照が新しいモデルを指すようにします。文字列参照を使用していない場合は、古いモデルをmodels.py(削除しないでください)の一番下に移動して、インポートされたクラスと競合しないようにします。
  4. 実行しますmakemigrationsが、何もラップしないでくださいstate_operations(FKの変更は実際に行われるはずです)。すべてに依存関係を追加ForeignKey移行(すなわちAlterFieldまで)CreateTableでの移行app2(あなたはので、それらを追跡し、次のステップのために、このリストが必要になります)。例えば:

    • CreateModeleg を含むマイグレーションを見つけ、そのマイグレーションapp2.migrations.0002_auto_<date>の名前をコピーします。
    • そのモデルへの外部キーを持つすべての移行app2.YourModelを見つけます(たとえば、次のような移行を検索して見つけます)。

      class Migration(migrations.Migration):
      
          dependencies = [
              ('otherapp', '0001_initial'),
          ]
      
          operations = [
              migrations.AlterField(
                  model_name='relatedmodel',
                  name='fieldname',
                  field=models.ForeignKey(... to='app2.YourModel'),
              ),
          ]
    • CreateModel移行を依存関係として追加します。

      class Migration(migrations.Migration):
      
          dependencies = [
              ('otherapp', '0001_initial'),
              ('app2', '0002_auto_<date>'),
          ]  
  5. からモデルを削除 app1

  6. で移行を実行makemigrationsしてラップapp1state_operationsます。
    • 前のステップからのすべてのForeignKeyマイグレーション(つまりAlterField)に依存関係を追加します(app1およびのマイグレーションが含まれる場合がありますapp2)。
    • これらの移行を作成したとき、DeleteTableすでに移行に依存していたAlterFieldため、手動で強制する必要がありませんでした(つまり、Alter以前Delete)。

この時点で、Djangoで問題ありません。新しいモデルは古いテーブルをポイントしており、Djangoの移行により、すべてが適切に再配置されたと確信しています。(@Michaelの回答による)大きな注意点ContentTypeは、新しいモデルに対して新しいものが作成されることです。ForeignKeyコンテンツタイプにリンクする(など)場合は、移行を作成してContentTypeテーブルを更新する必要があります。

私は自分自身(メタオプションとテーブル名)をクリーンアップしたかったので、次の手順(@Michaelから)を使用しました。

  1. db_tableメタエントリを削除する
  2. makemigrations再度実行してデータベースの名前変更を生成します
  3. この最後のマイグレーションを編集して、DeleteTableマイグレーションに依存していることを確認してください。Delete純粋に論理的である必要があるので、それは必要であるようには見えapp1_yourmodelませんが、もしそうでなければエラー(たとえば、存在しない)に遭遇しました。

これは完璧に機能しました、ありがとうございます!いずれにしても、これは依存関係ツリーの最下部にあるため、最後の移行の編集は重要だとは思いません。
James Meakin

1
いい答えだ!migrations.SeparateDatabaseAndStateに右括弧を追加する必要があると思いますよね?
atm

これでうまくいきました。@JamesMeakinのような最後の移行(ステップ3、回答全体の最後の行)も編集しませんでした。それでも問題なく動作しました
メガワット

:2番目のシナリオでは、FKSとの一つは、第二段階は、理にかなっているエラーで私のために失敗したtable_name: (models.E028) db_table 'table_name' is used by multiple models: app1.Model, app2.Model.
ミアイ・ザンファイア

この手順を数回使用しました。2.2(docs.djangoproject.com/en/2.2/ref/checks)と2.1(docs.djangoproject.com/en/2.1/ref/checks)のドキュメントを比較すると、2.2 で追加されたことがわかります。回避できる可能性がありますがmanaged=False、確認する場所がありません。
クレイトン

1

データが大きくないか、複雑すぎないが、維持することが依然として重要である場合の別のハックな代替策は、

  • manage.py dumpdataを使用してデータフィクスチャを取得する
  • 変更を関連付けずに、モデルの変更と移行を適切に進める
  • 古いモデルとアプリ名のフィクスチャを新しいものにグローバルに置き換えます
  • manage.py loaddataを使用してデータを読み込む

1

https://stackoverflow.com/a/47392970/8971048で私の回答からコピー

モデルを移動する必要があり、アプリにアクセスできない(またはアクセスしたくない)場合は、新しいオペレーションを作成し、移行したモデルがそうでない場合にのみ新しいモデルを作成することを検討できます。存在します。

この例では、old_appからmyappに「MyModel」を渡します。

class MigrateOrCreateTable(migrations.CreateModel):
    def __init__(self, source_table, dst_table, *args, **kwargs):
        super(MigrateOrCreateTable, self).__init__(*args, **kwargs)
        self.source_table = source_table
        self.dst_table = dst_table

    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        table_exists = self.source_table in schema_editor.connection.introspection.table_names()
        if table_exists:
            with schema_editor.connection.cursor() as cursor:
                cursor.execute("RENAME TABLE {} TO {};".format(self.source_table, self.dst_table))
        else:
            return super(MigrateOrCreateTable, self).database_forwards(app_label, schema_editor, from_state, to_state)


class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0002_some_migration'),
    ]

    operations = [
        MigrateOrCreateTable(
            source_table='old_app_mymodel',
            dst_table='myapp_mymodel',
            name='MyModel',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=18))
            ],
        ),
    ]

複数の質問に同じ回答を追加しないでください。最良のものに答え、残りを重複としてフラグを立てます。複数の質問に重複した回答を追加することは許容されますか?を
Petter Friberg、2017年

0

これは大まかにテストされているので、DBをバックアップすることを忘れないでください!!!

たとえば、2つのアプリがあります:src_appdst_app、モデルをMoveMeからsrc_appに移動したいとしdst_appます。

両方のアプリの空の移行を作成します。

python manage.py makemigrations --empty src_app
python manage.py makemigrations --empty dst_app

新しいマイグレーションがXXX1_src_app_newandでありXXX1_dst_app_new、以前の上位のマイグレーションがXXX0_src_app_oldandであると仮定しましょうXXX0_dst_app_old

MoveMeモデルのテーブルの名前を変更し、ProjectStateのそのapp_labelの名前をに変更する操作を追加しますXXX1_dst_app_newXXX0_src_app_old移行に依存関係を追加することを忘れないでください。結果のXXX1_dst_app_new移行は次のとおりです。

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

# this operations is almost the same as RenameModel
# https://github.com/django/django/blob/1.7/django/db/migrations/operations/models.py#L104
class MoveModelFromOtherApp(migrations.operations.base.Operation):

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

    def state_forwards(self, app_label, state):

        # Get all of the related objects we need to repoint
        apps = state.render(skip_cache=True)
        model = apps.get_model(self.old_app_label, self.name)
        related_objects = model._meta.get_all_related_objects()
        related_m2m_objects = model._meta.get_all_related_many_to_many_objects()
        # Rename the model
        state.models[app_label, self.name.lower()] = state.models.pop(
            (self.old_app_label, self.name.lower())
        )
        state.models[app_label, self.name.lower()].app_label = app_label
        for model_state in state.models.values():
            try:
                i = model_state.bases.index("%s.%s" % (self.old_app_label, self.name.lower()))
                model_state.bases = model_state.bases[:i] + ("%s.%s" % (app_label, self.name.lower()),) + model_state.bases[i+1:]
            except ValueError:
                pass
        # Repoint the FKs and M2Ms pointing to us
        for related_object in (related_objects + related_m2m_objects):
            # Use the new related key for self referential related objects.
            if related_object.model == model:
                related_key = (app_label, self.name.lower())
            else:
                related_key = (
                    related_object.model._meta.app_label,
                    related_object.model._meta.object_name.lower(),
                )
            new_fields = []
            for name, field in state.models[related_key].fields:
                if name == related_object.field.name:
                    field = field.clone()
                    field.rel.to = "%s.%s" % (app_label, self.name)
                new_fields.append((name, field))
            state.models[related_key].fields = new_fields

    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        old_apps = from_state.render()
        new_apps = to_state.render()
        old_model = old_apps.get_model(self.old_app_label, self.name)
        new_model = new_apps.get_model(app_label, self.name)
        if self.allowed_to_migrate(schema_editor.connection.alias, new_model):
            # Move the main table
            schema_editor.alter_db_table(
                new_model,
                old_model._meta.db_table,
                new_model._meta.db_table,
            )
            # Alter the fields pointing to us
            related_objects = old_model._meta.get_all_related_objects()
            related_m2m_objects = old_model._meta.get_all_related_many_to_many_objects()
            for related_object in (related_objects + related_m2m_objects):
                if related_object.model == old_model:
                    model = new_model
                    related_key = (app_label, self.name.lower())
                else:
                    model = related_object.model
                    related_key = (
                        related_object.model._meta.app_label,
                        related_object.model._meta.object_name.lower(),
                    )
                to_field = new_apps.get_model(
                    *related_key
                )._meta.get_field_by_name(related_object.field.name)[0]
                schema_editor.alter_field(
                    model,
                    related_object.field,
                    to_field,
                )

    def database_backwards(self, app_label, schema_editor, from_state, to_state):
        self.old_app_label, app_label = app_label, self.old_app_label
        self.database_forwards(app_label, schema_editor, from_state, to_state)
        app_label, self.old_app_label = self.old_app_label, app_label

    def describe(self):
        return "Move %s from %s" % (self.name, self.old_app_label)


class Migration(migrations.Migration):

    dependencies = [
       ('dst_app', 'XXX0_dst_app_old'),
       ('src_app', 'XXX0_src_app_old'),
    ]

    operations = [
        MoveModelFromOtherApp('MoveMe', 'src_app'),
    ]

への依存関係を追加XXX1_dst_app_newXXX1_src_app_newます。後に移行が確実に実行されるようXXX1_src_app_newにするために必要な何もしない移行です。src_appXXX1_dst_app_new

MoveMeからsrc_app/models.pyに移動しdst_app/models.pyます。次に実行します:

python manage.py migrate

それで全部です!


このコードはおそらくdjango 1.7でのみ役立つことに注意してください。django 2.0でこれを試してもうまくいきません。これはまた、このメカニズムを使用してモデルを移動すると、djangoバージョンのアップグレードにメンテナンスのオーバーヘッドが追加されることを意味します。
Paulが 't Hout

0

以下を試すことができます(テストされていません):

  1. モデルをからsrc_appに移動するdest_app
  2. 移行dest_app; スキーマの移行が最新のsrc_app移行に依存していることを確認してください(https://docs.djangoproject.com/en/dev/topics/migrations/#migration-files
  3. へのデータ移行を追加し、dest_appすべてのデータをからコピーしますsrc_app
  4. 移行src_app; スキーマの移行が最新の(データ)移行に依存していることを確認しますdest_app-つまり、ステップ3の移行

テーブルを移動するのではなく、全体をコピーすることに注意してください。そうすれば、両方のアプリが他のアプリに属する​​テーブルに触れる必要がなくなります。


0

モデルTheModelをapp_aからapp_bに移動するとします。

代替ソリューションは、既存の移行を手動で変更することです。アイデアは、app_aのマイグレーションでTheModelを変更するオペレーションを見るたびに、そのオペレーションをapp_bの最初のマイグレーションの最後にコピーするというものです。そして、app_aのマイグレーションに参照「app_a.TheModel」が表示されるたびに、それを「app_b.TheModel」に変更します。

これは、特定のモデルを再利用可能なアプリに抽出する必要がある既存のプロジェクトで行っただけです。手順はスムーズに進みました。app_bからapp_aへの参照があった場合、状況はさらに困難になると思います。また、私が手助けしたかもしれない私のモデルのために手動で定義されたMeta.db_tableを持っていました。

特に、移行履歴が変更されることになります。元の移行が適用されたデータベースがある場合でも、これは問題ではありません。元の移行と書き換えられた移行の両方が同じデータベーススキーマになる場合、そのような書き換えは問題ありません。


0
  1. 古いモデルの名前を「model_name_old」に変更します
  2. 移行する
  3. 「model_name_new」という名前の新しいモデルを、関連するモデルと同じ関係で作成します(たとえば、ユーザーモデルにはuser.blog_oldとuser.blog_newが含まれるようになります)
  4. 移行する
  5. すべてのデータを新しいモデルテーブルに移行するカスタム移行を作成する
  6. 移行の実行前後にバックアップを新しいdbコピーと比較して、これらの移行の地獄をテストします
  7. すべて問題なければ、古いモデルを削除します
  8. 移行する
  9. 新しいモデルを正しい名前 'model_name_new'-> 'model_name'に変更します
  10. ステージングサーバーで移行全体をテストする
  11. ユーザーの介入なしにすべての移行を実行するために、本番サイトを数分間停止します

移動する必要があるモデルごとにこれを個別に実行します。整数に変更して外部キーに戻すことで、他の答えが言うことを行うことはお勧めしません。移行後に新しい外部キーが異なり、行に異なるIDが含まれる可能性があり、リスクを実行したくありません外部キーに切り替えるときにIDの不一致が発生する。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.