南移多表继承 [英] South migration for multi-table inheritance

查看:165
本文介绍了南移多表继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个以前从模型继承的模型。模型,现在我重构了它们继承自相同的基本模型。 Django正在为此使用多表继承,我正在为此生成一个模式和数据迁移。



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



继承之前



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

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



继承后< h2>

 类已发布(models.Model):
published_on = models.DateTimeField()

class BlogPost(发布):
name = models.CharField()

class AudioFile(发布):
file = models.FileField()



迁移



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

./ manage.py schemamigration ap p -auto



生成的文件:

  class Migration(SchemaMigration):
def forward(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',['发布'])

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('a pp_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:

 列published_ptr_id包含空值


解决方案

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


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

      db.create_table('app_published',(
    ('id',self.gf('django.db.models.fields.AutoField') ($)
    ('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 orm.BlogPost.objects.all():
    published = orm。发布的.objects.create(published_on = blogpost.published_on)
    blogpost.published_ptr =已发布
    blogpost.save()

    在orm.AudioFile.objects.all()中的audiofile :
    published = orm.Published.objects.create(published_on = audiofile.published_on)
    audiofile.published_ptr = published
    audiofile.save()


  3. 模式迁移以从旧模型中删除(现在未使用)的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')(默认=无,为= ORM [ 'app.Published'],NULL = FALSE))
    db.alter_column( 'app_audiofile',published_ptr ,self.gf( 'django.db.models.fields.related.OneToOneField')(默认=无,为= ORM [ 'app.Published'],NULL = FALSE))

    分贝.create_index( 'app_blogpost',[ 'published_ptr'],独特=真)
    db.create_index( 'app_audiofile',[ 'published_ptr'],独特=真)
    db.create_primary_key( 'app_blogpost' ,[ 'published_ptr'])
    db.create_primary_key('app_audiofile ,[ published_ptr])



  4. I have a two models that previously inherited from models.Model and now I've refactored them to inherit from the same base model. Django is using multi-table inheritance for this and I'm trying to generate a schema and data migration for this. There is existing data in the database which needs to be migrated.

    I know that Django creates a OneToOneField, but I don't understand how it affects existing items in the database.

    Before Inheritance

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

    After inheritance

    class Published(models.Model):
        published_on = models.DateTimeField()
    
    class BlogPost(Published):
        name = models.CharField()
    
    class AudioFile(Published):
        file = models.FileField()
    

    Migration

    This was basically the migration that was generated when I ran:

    ./manage.py schemamigration app --auto.

    Generated file:

    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)
    

    When I try to run it, it raises an IntegrityError:

    column "published_ptr_id" contains null values
    

    解决方案

    You're going to need to break that into three migrations:

    1. Schemamigration to create the app_published table, and add your two new published_ptr columns. Add these new columns with null=True instead of with 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. Datamigration to iterate over your existing audiofiles and blogposts. The code is basically:

      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 to remove the (now unused) id and published_on columns from your old models. Also, change published_ptr from null=True to primary_key=True on the old models.

      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'])
      

    这篇关于南移多表继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆