70

すでにデータが含まれているデータベーステーブルを持つdjangoプロジェクトがあります。その列のデータを失うことなく、フィールド名を変更したいと思います。私の当初の計画は、dbテーブルの名前を実際には変更しない方法でモデルフィールド名を変更することでした(db_column列パラメーターを使用)。

元のモデル:

class Foo(models.Model):
  orig_name = models.CharField(max_length=50)

新しいモデル:

class Foo(models.Model):
  name = models.CharField(max_length=50, db_column='orig_name')

ただし、Southを実行すると、元の列を削除し、新しい列を追加するschemamigration --auto移行スクリプトが生成されます。これにより、その列のデータが削除されるという望ましくない副作用が発生します。(データベーステーブルの列の名前を変更せずにモデルフィールド名を変更できるというdb_columnの理解から、Southがdbの列の名前を変更したい理由についても混乱しています)。 orig_namename

dbフィールドを変更せずにモデルフィールドを変更することをやめられない場合は、次のように、より簡単な名前の変更を行うことができると思います。

元のモデル:

class Foo(models.Model):
  orig_name = models.CharField(max_length=50)

新しいモデル:

class Foo(models.Model):
  name = models.CharField(max_length=50)

最終的にどの戦略を使用するかに関係なく(最初の戦略を優先しますが、2番目の戦略を受け入れます)、私の主な関心事は、その列に既にあるデータを失わないようにすることです。

これには複数のステップのプロセスが必要ですか?(1.列の追加、2。古い列から新しい列へのデータの移行、3。元の列の削除など)または、移行スクリプトを次のように変更できdb.alter_columnますか?

列の名前を変更しながら、その列のデータを保持するための最良の方法は何ですか?

4

10 に答える 10

58

DBフィールドを保持したままフィールド名を変更する

Django 1.8以降の回答を追加します(SouthではなくDjangoネイティブの移行を使用)。

最初にdb_columnプロパティを追加し、次にフィールドの名前を変更する移行を行います。Djangoは、最初の操作がノーオペレーション(db_column同じままになるように変更するため)であり、2番目の操作がノーオペレーション(スキーマの変更がないため)であることを理解しています。実際にログを調べて、スキーマに変更がないことを確認しました...

operations = [
    migrations.AlterField(
        model_name='mymodel',
        name='oldname',
        field=models.BooleanField(default=False, db_column=b'oldname'),
    ),
    migrations.RenameField(
        model_name='mymodel',
        old_name='oldname',
        new_name='newname',
    ),
]
于 2015-10-17T21:10:56.343 に答える
46

Django 2.0.9(およびそれ以降)は、フィールドの名前が変更されたかどうかを自動的に検出し、削除して新しいフィールドを作成する代わりに名前を変更するオプションを提供します

( Django 2.2でも同じように機能します) ここに画像の説明を入力してください

最初の答え

それでも誰かに役立つ場合は、投稿します。

Django 2.0 +の場合、モデルのフィールドの名前を変更するだけです

class Foo(models.Model):
    orig_name = models.CharField(max_length=50)

class Foo(models.Model):
    name = models.CharField(max_length=50)

次に実行python manage.py makemigrations します。古いフィールドを削除して新しいフィールドを追加するための操作を含む移行が生成されます。

先に進み、それを次のように変更します。

operations = [
    migrations.RenameField(
        model_name='foo',
        old_name='orig_name',
        new_name='name')
]

次に実行するpython manage.py migrateと、データを失うことなくDBの列の名前が変更されます。

于 2019-01-31T12:01:30.233 に答える
18

修正は非常に簡単です。ただし、移行は自分で変更する必要があります。

列を削除して追加する代わりに、を使用しますdb.rename_column。によって作成された移行を簡単に変更できますschemamigration --auto

于 2010-08-16T23:14:07.530 に答える
10

実際、Django 1.10では、モデル内のフィールドの名前を変更してからmakemigrationsを実行するだけで、操作がすぐに識別されます(つまり、1つのフィールドが消え、別のフィールドが代わりに表示されます)。

$ ./manage.py makemigrations
Did you rename articlerequest.update_at to articlerequest.updated_at (a DateTimeField)? [y/N] y
Migrations for 'article_requests':
  article_requests/migrations/0003_auto_20160906_1623.py:
    - Rename field update_at on articlerequest to updated_at
于 2016-09-06T16:26:51.240 に答える
5

私はこの状況に遭遇しました。モデルのフィールド名を変更したかったのですが、列名は同じままにしました。

私がやった方法は、やることですschemamigration --empty [app] [some good name for the migration]。問題は、Southに関する限り、モデルのフィールド名を変更することは、モデルが処理する必要のある変更であるということです。したがって、移行を作成する必要があります。ただし、データベース側で実行する必要のあることは何もありません。したがって、空の移行は、データベースで不要な操作を行うことを回避し、それでも、変更と見なされるものを処理するサウスのニーズを満たします。

loaddataDjangoのテストフィクスチャ機能(loaddata舞台裏で使用)を使用または使用する場合は注意してください。フィクスチャはデータベースフィールド名ではなくモデルフィールド名に基づいているため、新しいフィールド名を使用するにはフィクスチャを更新する必要があります。

データベースで列名が変更される場合はdb.rename_column、列の移行に使用することをお勧めしません。私はこの答えでsjhによって記述された方法を使用します:

新しい列を1つのスキーマ移行として追加し、データ移行を作成して値を新しいフィールドに移動し、2番目のスキーマ移行を作成して古い列を削除しました

その質問へのコメントで述べたように、問題db.rename_columnは、列と一緒に制約の名前を変更しないことです。問題が単なる表面的なものなのか、それとも制約が見つからないために将来の移行が失敗する可能性があるのか​​は、私にはわかりません。

于 2015-01-29T13:07:24.987 に答える
4

手動で移行ファイルを編集せずに、フィールドの名前を変更することができます。

▶✧次のようなものから始めます。

class Foo(models.Model):
  old_name = models.CharField(max_length=50)

▶✧元のフィールドにdb_column= OLD_FIELD_NAMEを追加します。

class Foo(models.Model):
  old_name = models.CharField(max_length=50, db_column='old_name')

▶✧実行:python3 manage.py makemigrations

▶✧フィールドの名前をOLD_FIELD_NAMEからNEW_FIELD_NAME変更します

class Foo(models.Model):
  new_name = models.CharField(max_length=50, db_column='old_name')

▶✧実行:python3 manage.py makemigrations

プロンプトが表示されます:

MODELの名前を変更しましたか。OLD_FIELD_NAMEからMODELへ。NEW_FIELD_NAME(ForeignKey)?[y / N] y

これにより、1つではなく、2つの移行ファイルが生成されますが、両方の移行は自動生成されます。

この手順はDjango1.7以降で機能します。

于 2015-12-22T23:07:21.663 に答える
2

私はDjango1.7.7でこの状況に遭遇しました。私は私のために働いた次のことをすることになった。

./manage.py makemigrations <app_name> --empty

migrations.RenameFieldデータベースに影響を与えない単純なサブクラスを追加しました。

class RenameFieldKeepDatabaseColumn(migrations.RenameField):
def database_backwards(self, app_label, schema_editor, from_state, to_state):
    pass

def database_forwards(self, app_label, schema_editor, from_state, to_state):
    pass
于 2015-11-10T21:16:18.970 に答える
2

更新Django3.1では、一度に1つのフィールドのみを変更するのは非常に簡単です。

私の場合:

古いフィールド名は次is_admin のとおりです。新しいフィールド名は次のとおりです。is_superuser

それによって移行をpython manage.py makemigrations行うと、フィールドの名前を変更するかどうかを尋ねられました。そしてy、名前を変更するためにヒットしました。次に、によって移行しpython manage.py migrateます。私の場合の端末履歴は次のようになります。 ここに画像の説明を入力してください

:一度に複数のフィールドでテストしませんでした。

于 2020-11-11T05:54:14.707 に答える
0

他の応答で指摘されているように、データベースで変更を加えずに、を使用してフィールドの名前を変更するのは非常に簡単db_columnです。ただし、生成された移行により、実際にはいくつかのSQLステートメントが作成されます。./manage.py sqlmigrate ...移行を呼び出すことで、それを確認できます。

データベースへの影響を回避するSeparateDatabaseAndStateには、DBで何かを行う必要がないことをDjangoに示すために使用する必要があります。

あなたがそれについてもっと知りたいのなら、私はそれについての小さな記事を書きました。

于 2021-03-10T10:37:11.017 に答える
-1

1.djangoモデルのフィールド名を編集します

2.次のように空の移行を作成します。

$ python manage.py makemigrations --empty testApp(testAppはアプリケーション名です)

  1. 最近作成された空の移行ファイルを編集します

    Operations = [migrations.RenameField('your model'、'old field'、'new field')、]

  2. 移行を適用します
    $pythonmanage.pymigrate

データベースの列名が新しい名前に変更されます。

于 2021-05-20T07:44:20.377 に答える