2016-09-22 110 views
3

我有一个生产数据库,需要保证数据的安全。我想要更改模型中的Field,并使用此更改转换该数据库内的所有数据。在AlterField django迁移上转换数据

老场

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

回答

3

,我总是做最安全的方法是:

  1. 创建另一场field_name_new = models.PositiveIntegerField()
  2. 迁移生产数据库这一新领域
  3. 做数据迁移(转换field_name值和移动 转换价值字段field_name_new
  4. 更改您的代码以便使用field_name_new
  5. 部署步骤4
  6. 删除字段field_name
  7. 迁移生产分贝的步骤6和部署它(步骤6)

只有一个不好的一面:你可能会失去一些数据在步骤4和5,但你可以复制这些数据到新的领域基本上

6

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

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


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可能需要进行调整,但你的想法。

+0

这很有趣,我也会试试。谢谢 –