web-dev-qa-db-ja.com

Djangoモデルの関数としてデフォルトでフィールドを追加

Djangoモデルにnull不可の新しいフィールドを追加し、移行を使用してその変更をデプロイしようとしています。既存のモデルに使用するデフォルト値をそれらの機能にするには定数ではなくモデル?

例として、以前にcreated_onフィールドがあり、その値を最初にモデルのupdated_onに設定したいcreated_onフィールドを追加したとしましょう。移行でこれを行うにはどうすればよいですか?

これは私が始めようとしているものです:

    migrations.AddField(
        model_name='series',
        name='updated_as',
        field=models.DateTimeField(default=????, auto_now=True),
        preserve_default=False,
    ),
40
Alex Rothberg

単一の移行でこれを行う方法を学びました!

makemigrations Djangoを実行すると、1回限りのデフォルトを設定するように求められます。それを満足させるためにここでできることを定義すれば、移行AddFieldあなたが言及しました。

migrations.AddField(
    model_name='series',
    name='updated_as',
    field=models.DateTimeField(default=????, auto_now=True),
),

この1つの操作を3つの操作に変更します。

  1. 最初はフィールドをヌル可能にし、列が追加されます。
  2. 必要に応じてフィールドを設定する関数を呼び出します。
  3. フィールドを(AlterFieldで)変更して、nullを許可しないようにします(上記と同様、デフォルトなし)。

そのため、次のような結果になります。

migrations.AddField(
    model_name='series',
    name='updated_as',
    field=models.DateTimeField(null=True, auto_now=True),
),
migrations.RunPython(set_my_defaults, reverse_func),
migrations.AlterField(
    model_name='series',
    name='updated_as',
    field=models.DateTimeField(auto_now=True),
),

あなたの関数は次のようなものとして定義されています:

def set_my_defaults(apps, schema_editor):
    Series = apps.get_model('myapp', 'Series')
    for series in Series.objects.all().iterator():
        series.updated_as = datetime.now() + timedelta(days=series.some_other_field)
        series.save()

def reverse_func(apps, schema_editor):
    pass  # code for reverting migration, if any

あなたが知っていることを除いて、ひどいではありません。 F式 および/または データベース関数 を使用して、大規模データベースの移行パフォーマンスを向上させることを検討してください。

70
FraggaMuffin

2回の移行で行う必要があります。まず、フィールドを追加しますが、nullを許可します。通常どおり移行ファイルを作成します。その後、フィールドをnull不可に設定し、makemigrationsを再度実行しますが、まだ移行しないでください。 2番目の移行を開き、上部で関数を定義します。

def set_field_values(apps, schema_editor):
    # use apps.get_model("app_name", "model_name") and set the defualt values

次に、移行ファイルに操作のリストがあります。 フィールド変更操作add

RunPython(set_field_values)

そしてそれはそれを行う必要があります

19
Karolis Ryselis

また、将来的に移行を元に戻す場合に備えて、関数set_my_defaults()のリバースを定義する必要があります。

def reverse_set_default(apps, schema_editor):
    pass

この場合の逆関数は、フィールドを削除するため、何もする必要はありません。

それをRunPythonに追加します:

migrations.RunPython(set_my_defaults, reverse_set_default),
5
bnznamco