在AlterField django迁移上转换数据

时间:2016-09-22 00:55:53

标签: django django-models django-migrations

我有一个生产数据库,需要保持数据安全。我想更改模型中的Field并使用此更改转换该数据库中的所有数据。

旧场

class MyModel(models.Model):
    field_name = models.TimeField()

更改字段

class MyModel(models.Model):
    field_name = models.PositiveIntegerField()

基本上我想在几分钟内转换TimeField值(有一个Time对象)。

示例:我有一个对象time(hour=2, minute=0, second=0),我想在应用迁移时将所有数据库表中的字段值转换为120

2 个答案:

答案 0 :(得分:13)

过去,我总是在Djangos RunPython操作的帮助下完成这项工作。创建一个处理以下内容的自定义迁移。

  1. 更改字段名称。
  2. 添加所需类型的新字段。
  3. RunPython处理从一个转换为另一个的逻辑。
  4. 删除旧字段。

  5. def migrate_time_to_positive_int(apps, schema_editor):
    
        MyModel = apps.get_model('myapp', 'MyModel')
    
        for mm in MyModel.objects.all():
    
            field_old_time = mm.field_name_old
            field_new_int = field_old_time.total_seconds() / 60
            mm.field_name = field_new_int 
            mm.save()
    
    class Migration(migrations.Migration):
    
        operations = [
            migrations.RenameField(
                model_name='mymodel',
                old_name='field_name',
                new_name='field_name_old',
            ),
            migrations.AddField(
                model_name='mymodel',
                name='field_name',
                field=models.PositiveIntegerField(),
            ),
            migrations.RunPython(migrate_time_to_positive_int),
            migrations.RemoveField(
                model_name='mymodel',
                name='field_name_old',
            )
        ]
    

    field_name_old.total_seconds()/ 60可能需要调整,但你明白了。

答案 1 :(得分:4)

我一直以来最安全的方式是:

  1. 使用field_name_new = models.PositiveIntegerField()
  2. 创建另一个字段
  3. 在生产数据库
  4. 上迁移此新字段
  5. 进行数据迁移(转换field_name值并移动 将值转换为字段field_name_new
  6. 更改您的代码,以便使用field_name_new
  7. 部署第4步
  8. 删除字段field_name
  9. 迁移生产数据库上的步骤6并部署它(步骤6)
  10. 只有一个不好的方面:您可能会在步骤4和5中丢失一些数据。但您可以将这些数据复制到新字段