Django Migrations添加默认为模型函数的字段

Ale*_*erg 42 django django-models django-migrations

我在我的Django模型中添加了一个新的,不可为空的字段,并尝试使用迁移来部署该更改.如何将现有模型的默认值设置为这些模型的某些函数而不是常量?

举一个例子,假设我之前有一个created_on字段,我刚刚添加了一个updated_on字段,其值我想先设置为模型created_on.我如何在迁移中执行此操作?

这就是我想要开始的:

    migrations.AddField(
        model_name='series',
        name='updated_as',
        field=models.DateTimeField(default=????, auto_now=True),
        preserve_default=False,
    ),
Run Code Online (Sandbox Code Playgroud)

Fra*_*fin 75

我刚学会了一次迁移怎么做!

运行makemigrationsdjango时应该要求你设置一次性默认值.定义您可以在这里保留的任何内容,并最终完成AddField您提到的迁移.

migrations.AddField(
    model_name='series',
    name='updated_as',
    field=models.DateTimeField(default=????, auto_now=True),
),
Run Code Online (Sandbox Code Playgroud)

将此操作更改为3个操作:

  1. 最初使字段可以为空,因此将添加该列.
  2. 调用函数以根据需要填充字段.
  3. 改变字段(with AlterField)使其不可为空(如上所述,没有默认值).

所以你最终得到类似的东西.

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),
),
Run Code Online (Sandbox Code Playgroud)

将您的函数定义为:

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
Run Code Online (Sandbox Code Playgroud)

除此之外,你知道,并不可怕; 考虑使用F表达式和/或数据库函数来提高大型数据库的迁移性能.

  • 你可以使用:Series.objects.all().update(updated_as = datetime.now()+ timedelta(days = series.some_other_field))#update用作单个请求 (4认同)
  • 而不是`reverse_func`,您应该使用`migrations.RunPython.noop`。检查文档以获取更多详细信息-https://docs.djangoproject.com/zh-CN/2.1/ref/migration-operations/#django.db.migrations.operations.RunPython.noop (2认同)

Kar*_*lis 19

您需要在两次迁移中执行此操作.首先,添加你的字段,但可以为空.像往常一样创建迁移文件.之后,将您的字段设置为不可为空,并再次运行makemigrations,但不要进行迁移.打开第二个迁移并在顶部定义一个函数:

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

然后,在您的迁移文件中有一个操作列表. alter field操作之前添加

RunPython(set_field_values)
Run Code Online (Sandbox Code Playgroud)

它应该这样做


小智 5

您还应该为您的函数定义一个反向set_my_defaults(),以防将来要恢复迁移。

def reverse_set_default(apps, schema_editor):
    pass
Run Code Online (Sandbox Code Playgroud)

在这种情况下,反向功能不需要执行任何操作,因为您要删除该字段。

并将其添加到RunPython:

migrations.RunPython(set_my_defaults, reverse_set_default),
Run Code Online (Sandbox Code Playgroud)

  • 如果您只是使用带有“pass”的函数,则应该使用“migrations.RunPython.noop”。所以“migrations.RunPython(set_my_defaults,migrations.RunPython.noop)” (2认同)