Django south 我可以将模式和数据(南部)迁移合并为一个迁移吗?

Django south 我可以将模式和数据(南部)迁移合并为一个迁移吗?,django-south,Django South,我想使用South将字段按一下并将其数据从一个模型移动到另一个模型: Foo类(models.Model): foofield=models.CharField() honk=models.PositiveIntegerField() 类栏(models.Model): barfield=models.CharField() 我以前使用过3次单独的迁移: 架构迁移,将鸣叫添加到栏 数据迁移,将所有Foo.honk数据复制到Bar.honk 另一个模式迁移,从Foo 我可以在一次迁移中完成这三个

我想使用South将字段按一下并将其数据从一个模型移动到另一个模型:

Foo类(models.Model):
foofield=models.CharField()
honk=models.PositiveIntegerField()
类栏(models.Model):
barfield=models.CharField()
我以前使用过3次单独的迁移:

  • 架构迁移,将鸣叫添加到
  • 数据迁移,将所有Foo.honk数据复制到Bar.honk
  • 另一个模式迁移,从Foo
  • 我可以在一次迁移中完成这三个步骤吗? 我已经了解到了这一点,所以我想也许类似的方法可以奏效(这是上面三次迁移合并在一起的结果):

    类迁移(数据迁移):
    def转发(自身、orm):
    #添加列
    db.add_列('myapp_bar','honk',self.gf('django.db.models.fields.PositiveIntegerField')(默认值为0'),保留_默认值为False)
    #复制数据
    对于foo.objects.all()中的foo:
    #在这里找到正确的酒吧,然后。。。
    bar.honk=foo.honk
    bar.save()
    #删除旧列
    db.delete_列('myapp_foo','honk')
    

    因为我的(南方冰冻)orm还不知道Bar.honk,所以这会起作用还是失败?还是我做错了,在一次迁移中有更好的方法来做这类事情?

    自从这个问题为我赢得了一个好的答案,我自己就开始尝试了。这是我发现的

    不,您不能合并这些迁移 因为ORM冻结只包含要迁移到的架构。因此,在上面的示例中,foo.honk在数据迁移过程中不可访问(for
    循环),因为它在模式迁移过程中被删除,因此不在冻结的ORM中。此外,如果您试图访问数据,则会出现DatabaseError异常,因为数据库中的列与模型中的列不匹配(即,如果您试图访问数据库中的任何列,则会出现DatabaseError异常

    看起来没有简单的快捷方式,这样做需要进行上面提到的3次迁移。

    这对我很有用:

    def migratedata(orm):
       # copy data, need to lookup model through orm.
       for foo in orm['myapp.foo'].objects.all():
          # find the right bar here and then ...
          bar.honk = foo.honk
          bar.save()
    
    class Migration(SchemaMigration):
       def forwards(self, orm):
          # add column
          db.add_column('myapp_bar', 'honk', self.gf('django.db.models.fields.PositiveIntegerField')(default='0'), keep_default=False)
          # migrate data
          if not db.dry_run:
             migratedata(orm)
          # remove old column
          db.delete_column('myapp_foo', 'honk')
    

    然而,我不推荐它,因为它很容易搞砸。需要特别注意唯一性和操作顺序(注意,删除相关字段(:)后不要迁移数据)

    从这个角度来看,文档是缺乏的,但是如果您在迁移中修改ORM的冻结部分,添加您自己缺少的字段,那么它将是可访问的:我的意思是,在南迁移期间,您必须使用冻结的ORM,因为在将来迁移时,
    Foo
    模型可能已经丢失了e
    按喇叭
    字段

    我认为,如果您像下面这样修改冻结的ORM声明

    模型={
    “app.foo”:{
    'Meta':{'object_name':'Foo'},
    'id':('django.db.models.fields.AutoField',[],{'primary_key':'True'}),
    'foofield':('django.db.models.fields.CharField',[],{'max_length':666}),
    'honk':('django.db.models.fields.PositiveIntegerField',[],{}),
    },
    “应用程序栏”:{
    'Meta':{'object_name':'Bar'},
    'id':('django.db.models.fields.AutoField',[],{'primary_key':'True'}),
    'barfield':('django.db.models.fields.CharField',[],{'max_length':666}),
    'honk':('django.db.models.fields.PositiveIntegerField',[],{}),
    },
    }
    完成应用程序=['app']
    对称=真
    
    一切都会好起来的:)

    诀窍是在每个模型中定义字段
    honk
    ,显然数据库中的列必须存在

    类迁移(数据迁移):
    def转发(自身、orm):
    #添加列
    db.add_列('myapp_bar','honk',self.gf('django.db.models.fields.PositiveIntegerField')(默认值为0'),保留_默认值为False)
    #复制数据
    对于foo.objects.all()中的foo:
    #在这里找到正确的酒吧
    bar=orm.bar.objects.get(**随便)
    bar.honk=foo.honk
    bar.save()
    #删除旧列
    db.delete_列('myapp_foo','honk')
    

    PS:正如@acjohnson55
    symmetric=True所指出的
    非常重要

    正如Ingmar所提到的,南方ORM在特定的时间点被冻结,这会阻止你访问ORM不知道的列。然而,实际上有一种解决方法:您不必使用ORM,甚至不必使用任何ORM;相反,你可以

    比如说

    for foo in Foo.objects.all():
        print foo.honk
    
    您可以执行以下操作:

    cursor.execute('SELECT "honk" FROM "myapp_foo"')
    for honk, in cursor.fetchall():
        print honk
    

    我想补充一点,这就是数据迁移中的
    symmetric=True
    。假设数据迁移前后有一个一致的模式,因此您可以使用
    orm
    向前
    向后
    迁移中访问冻结的模型。因为在模式迁移中不是这样,所以在模式迁移中不应移动数据。另外,不要在数据迁移中导入模型名称;而是从
    orm
    中的冻结模型中为这些名称赋值。手册对此不是非常清楚,所以我想我应该在这里包含这些信息。我刚刚合并了迁移,类似于使用south的db.execute方法进行数据操作的迁移。此外,您还需要使用db.start\u transaction和db.commit\u transaction将架构和数据更改划分为单独的事务。@clime即使使用事务,似乎也很危险;如果其中一个发生错误,是否有一半的迁移被提交的可能性?如果是这种情况,那么“迁移堆栈”可能处于不一致的状态,并且您将无法完全反转迁移。