Django 迁移添加具有默认值的字段作为模型的函数 [英] Django Migrations Add Field with Default as Function of Model

查看:38
本文介绍了Django 迁移添加具有默认值的字段作为模型的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我向我的 Django 模型添加了一个新的、不可为空的字段,并尝试使用迁移来部署该更改.我如何将用于现有模型的默认值设置为这些模型的某些函数而不是常量?

举个例子,假设我之前有一个 created_on 字段,我刚刚添加了一个 updated_on 字段,我想将其值最初设置为模型的 created_on.我将如何在迁移中执行此操作?

这就是我想要开始的:

 migrations.AddField(模型名称='系列',name='updated_as',field=models.DateTimeField(default=????, auto_now=True),保留默认值=假,),

解决方案

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

在运行 makemigrations 时,django 应该要求您设置一次性默认值.在这里定义你能做的一切,让它开心,你最终会得到你提到的迁移 AddField.

migrations.AddField(模型名称='系列',name='updated_as',field=models.DateTimeField(default=????, auto_now=True),保留默认值=假,),

把这一个操作改成3个操作:

  1. 最初使字段可以为空,以便添加该列.
  2. 调用函数以根据需要填充该字段.
  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:

  1. Initially make the field nullable, so the column will be added.
  2. Call a function to populate the field as needed.
  3. 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),
),

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.

这篇关于Django 迁移添加具有默认值的字段作为模型的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆