【问题标题】:South migration for multi-table inheritance多表继承南移
【发布时间】:2012-09-18 15:38:06
【问题描述】:

我有两个以前从 models.Model 继承的模型,现在我将它们重构为从同一个基本模型继承。 Django 正在为此使用多表继承,我正在尝试为此生成模式和数据迁移。 数据库中有现有数据需要迁移。

我知道 Django 创建了一个 OneToOneField,但我不明白它如何影响数据库中的现有项目。

继承前

class BlogPost(models.Model):
    name = models.CharField()
    published_on = models.DateTimeField()

class AudioFile(models.Model):
    file = models.FileField()
    published_on = models.DateTimeField()

继承后

class Published(models.Model):
    published_on = models.DateTimeField()

class BlogPost(Published):
    name = models.CharField()

class AudioFile(Published):
    file = models.FileField()

迁移

这基本上是我运行时生成的迁移:

./manage.py schemamigration app --auto.

生成的文件:

class Migration(SchemaMigration):
    def forwards(self, orm):
        db.create_table('app_published', (
            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
            ('published_on', self.gf('django.db.models.fields.DateTimeField')()),
        ))
        db.send_create_signal('app', ['Published'])

        db.delete_column('app_blogpost', 'published_on')
        db.delete_column('app_blogpost', 'id')
        db.add_column('app_blogpost', 'published_ptr', self.gf('django.db.models.fields.related.OneToOneField')(default=None, to=orm['app.Published'], unique=True, primary_key=True), keep_default=False)

        db.delete_column('app_audiofile', 'published_on')
        db.delete_column('app_audiofile', 'id')
        db.add_column('app_audiofile', 'published_ptr', self.gf('django.db.models.fields.related.OneToOneField')(default=None, to=orm['app.Published'], unique=True, primary_key=True), keep_default=False)

当我尝试运行它时,它会引发 IntegrityError:

column "published_ptr_id" contains null values

【问题讨论】:

    标签: django django-models django-south


    【解决方案1】:

    您需要将其分解为三个迁移:

    1. Schemamigration 创建 app_published 表,并添加两个新的 published_ptr 列。使用 null=True 而不是 primary_key=True 添加这些新列:

      db.create_table('app_published', (
          ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
          ('published_on', self.gf('django.db.models.fields.DateTimeField')()),
      ))
      db.add_column('app_blogpost', 'published_ptr', self.gf('django.db.models.fields.related.OneToOneField')(default=None, to=orm['app.Published'], null=True), keep_default=False)
      db.add_column('app_audiofile', 'published_ptr', self.gf('django.db.models.fields.related.OneToOneField')(default=None, to=orm['app.Published'], null=True), keep_default=False)
      
    2. 数据迁移以迭代您现有的音频文件和博客文章。代码基本上是:

      for blogpost in orm.BlogPost.objects.all():
          published = orm.Published.objects.create(published_on=blogpost.published_on)
          blogpost.published_ptr = published
          blogpost.save()
      
      for audiofile in orm.AudioFile.objects.all():
          published = orm.Published.objects.create(published_on=audiofile.published_on)
          audiofile.published_ptr = published
          audiofile.save()
      
    3. Schemamigration 从旧模型中删除(现在未使用的)id 和 published_on 列。另外,将旧模型上的 published_ptr 从 null=True 更改为 primary_key=True。

      db.delete_column('app_blogpost', 'published_on')
      db.delete_column('app_blogpost', 'id')
      db.delete_column('app_audiofile', 'published_on')
      db.delete_column('app_audiofile', 'id')
      
      db.alter_column('app_blogpost', 'published_ptr', self.gf('django.db.models.fields.related.OneToOneField')(default=None, to=orm['app.Published'], null=False))
      db.alter_column('app_audiofile', 'published_ptr', self.gf('django.db.models.fields.related.OneToOneField')(default=None, to=orm['app.Published'], null=False))
      
      db.create_index('app_blogpost', ['published_ptr'], unique=True)
      db.create_index('app_audiofile', ['published_ptr'], unique=True)
      db.create_primary_key('app_blogpost', ['published_ptr'])
      db.create_primary_key('app_audiofile', ['published_ptr'])
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多