【问题标题】:Django South - schema and data migration at the same timeDjango South - 同时进行模式和数据迁移
【发布时间】:2014-01-29 20:57:06
【问题描述】:

在架构迁移中是否可以使用 South 执行类似以下操作?

def forwards(self, orm):
    ## CREATION
    # Adding model 'Added'
    db.create_table(u'something_added', (
        (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
        ('foo', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['something.Foo'])),
        ('bar', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['something.Bar'])),
    ))
    db.send_create_signal(u'something', ['Added'])

    ## DATA
    # Create Added for every Foo
    for f in orm.Foo.objects.all():
        self.prev_orm.Added.objects.create(foo=f, bar=f.bar)

    ## DELETION
    # Deleting field 'Foo.bar'
    db.delete_column(u'something_foo', 'bar_id')  

查看prev_orm,这将使我能够访问f.bar,并一体化。我发现必须为此编写 3 个迁移非常繁重......

我知道这不是“做事的方式”,但在我看来,这确实会更干净。

顺便说一句,这样做会有真正的问题吗?

【问题讨论】:

  • 我会尝试在模型字典中包含“添加”模型。那么在create_table之后可能就可以使用self.orm.Added照常使用了,不过我没有测试。

标签: django django-south data-migration schema-migration


【解决方案1】:

南迁移使用transaction management

同时进行多个迁移时,代码类似于:

for migration in migrations:
    south.db.db.start_transaction()
    try:
        migration.forwards(migration.orm)
        south.db.db.commit_transaction()
    except:
        south.db.db.rollback_transaction()
        raise

所以...虽然不建议混合使用架构和数据迁移,但一旦您使用commit 架构和db.commit_transaction(),这些表应该可供您使用。请注意提供一个 backwards() 方法,该方法可以正确地向后退一步。

【讨论】:

    【解决方案2】:

    首先,South 提供的 orm 是您要迁移到的。换句话说,它在迁移完成后匹配架构。所以你可以写orm.Added而不是self.prev_orm.Added。这个事实的另一个含义是您不能引用foo.bar,因为它不存在于最终架构中。

    解决这个问题(并回答您的问题)的方法是跳过 ORM 并直接使用 execute raw SQL directly

    在您的情况下,访问已删除行的 create 语句如下所示:

    cursor.execute('SELECT "id", "bar_id" FROM "something_foo"')
    for foo_id, bar_id in cursor.fetchall()
        orm.Added.ojbects.create(foo_id=foo_id, bar_id=bar_id)
    

    【讨论】:

      【解决方案3】:

      我猜您的目标是确保在数据迁移之前不会运行删除。为此,您可以使用dependency system in South

      您可以将以上内容分为三个部分:

      001_app1_addition_migration(在应用程序 1 中)

      然后

      001_app2_data_migration(在应用程序 2 中,Foo 模型所属的位置)

      然后

      002_app1_deletion_migration(在应用程序 1 中)具有以下内容:

      class Migration:
      
          depends_on = (
              ("app2", "001_app2_data_migration"),
          )
      
          def forwards(self):
              ## DELETION
              # Deleting field 'Foo.bar'
              db.delete_column(u'something_foo', 'bar_id')
      

      【讨论】:

      • 好的。但我想做的是只写一个迁移,这让我的头脑更清楚......
      猜你喜欢
      • 1970-01-01
      • 2016-11-21
      • 1970-01-01
      • 2012-07-26
      • 1970-01-01
      • 2012-04-11
      • 1970-01-01
      • 1970-01-01
      • 2011-06-29
      相关资源
      最近更新 更多