Django迁移添加默认字段作为模型的函数

bfhwhh0e  于 12个月前  发布在  Go
关注(0)|答案(4)|浏览(104)

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

字符串

5m1hhzi4

5m1hhzi41#

我刚刚学会了如何通过一次迁移来实现这一点!
当运行makemigrations时,django会要求你设置一个一次性的默认值。在这里定义你能做的一切来保持它的快乐,你最终会得到你提到的AddField迁移。

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

字符串
将这一个操作改为3个操作:
1.最初使字段可为空,因此将添加列。
1.根据需要调用函数来填充字段。
1.改变字段(使用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 expressions和/或database functions来提高大型数据库的迁移性能。

rekjcdws

rekjcdws2#

您需要分两次迁移。首先,添加您的字段,但使其可为空。像往常一样创建一个迁移文件。之后,将您的字段设置为不可为空并再次运行makemigrations,但不要启动migrate。打开第二次迁移并在顶部定义一个函数:

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

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

RunPython(set_field_values)


它应该能做到

vm0i2vca

vm0i2vca3#

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

def reverse_set_default(apps, schema_editor):
    pass

字符串
在这种情况下,反向函数不需要做任何事情,因为您正在删除字段。
并将其添加到RunPython:

migrations.RunPython(set_my_defaults, reverse_set_default),

jc3wubiy

jc3wubiy4#

要将从现有字段中获取的默认值添加到新的不可为空的字段中,请按以下方式编写迁移:

  • 经营移民
  • null=True添加到生成的AddField语句中
  • 添加RunSQL语句,根据表中所有记录的现有字段填充新字段
  • 使用AlterField语句再次删除null=True
migrations.AddField(
    model_name='series',
    name='updated_as',
    field=models.DateTimeField(null=True, auto_now=True),
),
migrations.RunSQL(
    sql="UPDATE myapp_series SET updated_as = created_on",
    reverse_sql=migrations.RunSQL.noop
),
migrations.AlterField(
    model_name='series',
    name='updated_as',
    field=models.DateTimeField(auto_now=True),
),

字符串

相关问题