Django south 我可以将模式和数据(南部)迁移合并为一个迁移吗?
我想使用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 我可以在一次迁移中完成这三个
Foo类(models.Model):
foofield=models.CharField()
honk=models.PositiveIntegerField()
类栏(models.Model):
barfield=models.CharField()
我以前使用过3次单独的迁移:
类迁移(数据迁移):
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即使使用事务,似乎也很危险;如果其中一个发生错误,是否有一半的迁移被提交的可能性?如果是这种情况,那么“迁移堆栈”可能处于不一致的状态,并且您将无法完全反转迁移。