更新时间:2023-01-30 10:50:24
我刚刚学会了如何通过一次迁移来做到这一点!
在运行 makemigrations
时,django 应该要求您设置一次性默认值.在这里定义你能做的一切,让它开心,你最终会得到你提到的迁移 AddField
.
migrations.AddField(模型名称='系列',name='updated_as',field=models.DateTimeField(default=????, auto_now=True),保留默认值=假,),
把这一个操作改成3个操作:
AlterField
)使其不可为空(如上述,没有默认值).所以你最终会得到这样的结果:
migrations.AddField(模型名称='系列',name='updated_as',field=models.DateTimeField(null=True, auto_now=True),),migrations.RunPython(set_my_defaults, reverse_func),迁移.AlterField(模型名称='系列',name='updated_as',field=models.DateTimeField(auto_now=True),),
你的函数定义如下:
def set_my_defaults(apps, schema_editor):系列 = apps.get_model('myapp', 'Series')对于 Series.objects.all().iterator() 中的系列:series.updated_as = datetime.now() + timedelta(days=series.some_other_field)系列.save()def reverse_func(apps, schema_editor):pass # 用于恢复迁移的代码,如果有的话
除了,你知道,并不可怕.
注意:考虑使用 F 表达式和/或 数据库函数,用于提高大型数据库的迁移性能.>
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?
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!
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),
preserve_default=False,
),
Change this one operation into 3 operations:
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),
),
with your functions defined as something like:
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
Except, you know, not terrible.
Note: Consider using F expressions and/or database functions to increase migration performance for large databases.