Django迁移添加默认具有模型功能的字段 [英] Django Migrations Add Field with Default as Function of Model
问题描述
我在Django模型中添加了一个新的,不可为空的字段,并尝试使用迁移来部署该更改。
I added a new, non-nullable field to my Django model and am trying to use migrations to deploy that change. How would I set default value to use for existing models to be some function of those models rather than a constant?
作为示例,假设我以前有一个 created_on
字段,我刚刚添加了 updated_on
字段,其值最初要设置为模型的 created_on
。我将如何在迁移中做到这一点?
As an example let's say I previously had a created_on
field and I just added an updated_on
field whose value I want to set initially to the model's created_on
. How would I do this in a migration?
这就是我要开始的工作:
This is what I am trying to start with:
migrations.AddField(
model_name='series',
name='updated_as',
field=models.DateTimeField(default=????, auto_now=True),
preserve_default=False,
),
推荐答案
我刚刚学习了一次迁移的方法!
I just learnt how to do this with a single migration!
运行 makemigrations
时django应该要求您设置一个默认值。在这里定义任何可以让它开心的东西,最后都会得到您提到的迁移 AddField
。
when running makemigrations
django should ask you to set a one-off default. Define whatever you can here to keep it happy, and you'll end up with the migration AddField
you mentioned.
migrations.AddField(
model_name='series',
name='updated_as',
field=models.DateTimeField(default=????, auto_now=True),
),
将此操作更改为3个操作:
Change this one operation into 3 operations:
- 最初使该字段可为空,因此将添加该列。
- 调用一个函数来填充
- 更改字段(使用
AlterField
)以使其不为空(如上,没有默认值)
- initially make the field nullable, so the column will be added.
- call a function to populate the field as needed.
- alter the field (with
AlterField
) to make it not nullable (like the above, with no default).
所以您最终得到类似的东西。
so you end up with something like.
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表达式和/或数据库函数,以提高大型数据库的迁移性能。
Except, you know, not terrible; consider using F expressions and/or database functions to increase migration performance for large databases.
这篇关于Django迁移添加默认具有模型功能的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!