我在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,
),
答案 0 :(得分:67)
我刚刚学会了如何通过一次迁移来实现这一目标!
运行makemigrations
时,django会要求您设置一次性默认值。定义您可以在这里保留的任何内容,并最终得到您提到的迁移AddField
。
migrations.AddField(
model_name='series',
name='updated_as',
field=models.DateTimeField(default=????, auto_now=True),
),
将此操作更改为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 expressions和/或database functions来提高大型数据库的迁移性能。
答案 1 :(得分:18)
您需要在两次迁移中执行此操作。首先,添加你的字段,但可以为空。像往常一样创建迁移文件。之后,将你的领域设置为不可空,并再次运行makemigrations,但还没有迁移。打开第二个迁移并在顶部定义一个函数:
def set_field_values(apps, schema_editor):
# use apps.get_model("app_name", "model_name") and set the defualt values
然后,在您的迁移文件中有一个操作列表。 之前更改字段操作添加
RunPython(set_field_values)
它应该这样做
答案 2 :(得分:4)
您还应该为函数set_my_defaults()
定义一个反向,以防将来还原迁移的内容。
def reverse_set_default(apps, schema_editor):
pass
在这种情况下,反向功能无需执行任何操作,因为您要删除该字段。
并将其添加到RunPython:
migrations.RunPython(set_my_defaults, reverse_set_default),