当前位置 : 主页 > 手机开发 > 无线 >

如何在从一对一移动到一对多时执行数据迁移

来源:互联网 收集:自由互联 发布时间:2021-06-10
我正在使用南方来管理迁移,我已经到了一个角落.基本上我有以下设置: 应用1: class A(models.Model): # bunch of attributes 应用2: class B(models.Models): instance_a = models.OneToOneField(A, null=True, blank
我正在使用南方来管理迁移,我已经到了一个角落.基本上我有以下设置:

应用1:

class A(models.Model):
  # bunch of attributes

应用2:

class B(models.Models):
  instance_a = models.OneToOneField(A, null=True, blank=True, 
                                    editable=False)

现在,我想从此到此:

应用1:

class A(models.Model):
  instance_b = models.ForeignKey(B, null=True, blank=True)

应用2:

class B(models.Models):
  # other attributes

我的主要问题是我不能丢失数据.因此,基本上在迁移结束时,先前映射到对象B的所有对象A应保持该映射.例如,如果具有id 7的对象A被映射到具有id 8的对象B,则在该过程结束时应该保留该映射.

我尝试了一些与临时占位符和数据迁移混合的模式迁移.但是我最终总是在同一个地方,这是在执行数据迁移时我不再拥有先前的关系以便访问正确的属性.例如,B.instance_a不再可用.

我希望你对两件事有所了解:

>首先,这是否可行只使用南方迁移.
>其次,我该怎么办呢.

谢谢

终于过了一段时间,我得到了一个django-south的程序,可以帮助别人.关键是南方的depends_on功能(http://south.aeracode.org/wiki/Dependencies).我分四步完成:

第一:

>为模型A中的外键值创建占位符.

所以模型A变成:

class A(models.Model):
    instance_b_placeholder = models.ForeignKey(A, null=True, blank=True)

现在运行manage.py schemamigration app1 –auto.

第二

>创建数据迁移,以便我们可以复制值.目标是将数据复制到数据库中,稍后重命名属性并删除旧属性.发出manage.py datamigration app1 update_fields.我选择在app1中保留数据迁移.如果您不这样做,请确保它在上一次迁移后运行.

这是数据移植编码:

# Forwards:

for b in orm['app2.B'].objects.filter(instance_b__isnull=False):
        b.instance_a.instance_b_placeholder = b
        b.instance_a.save()

# Backwards:

for r in orm['app1.A'].objects.filter(instance_b_placeholder__isnull=False):
        r.instance_b_placeholder.instance_a = r
        r.instance_b_placeholder.save()

第三:

>从模型B中删除字段instance_b,并确保在上一步中创建的迁移之后运行迁移.

模型B变为:

class B(models.Model):
     # etc...

发出manage.py schemamigration app2 –auto并编辑迁移,将先前的迁移添加到depends_on:

depends_on = (
    ("app1", "<migration_number>_update_fields"),
)

第四步:

>重命名占位符.这是通过更改代码中的名称和编辑迁移来实现的.编辑是必要的,因为南方倾向于删除并添加新列,但我们只希望它重命名该列.
>此迁移应该在最后一个位置运行,因此我依赖于前一个迁移.

这是代码:

depends_on = (
    ("app2", "<previous_migration_here>"),
)

# Forwards:

    db.rename_column('app1_a', 'instance_b_placeholder_id', 'instance_b_id')

# Backwards:

    db.rename_column('app1_a', 'instance_b_id', 'instance_b_placeholder_id')

就是这样了.我不知道是否还有很多其他方法可以做到这一点,但至少这对我有帮助.

网友评论