一尘不染

Django迁移添加默认具有模型功能的字段

django

我在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,
    ),

阅读 365

收藏
2020-04-02

共1个答案

一尘不染

我刚刚学习了如何通过一次迁移来做到这一点!

当运行makemigrationsdjango时,应要求你设置一个默认值。在这里定义所有可以使它满意的内容,最后将完成AddField你提到的迁移。

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

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

  1. 最初使该字段可为空,因此将添加该列。
  2. 调用一个函数以根据需要填充该字段。
  3. 更改字段(带有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),
),

你的函数定义为:

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表达式和/或数据库函数来提高大型数据库的迁移性能。

2020-04-02