使用Django South从具体继承过渡到抽象继承


问题内容

我有一个现有的Django项目,该项目具有几个使用基类的具体继承的模型。经过仔细考虑,并阅读了诸如Jacob Kaplan-
Moss之类的人所说的话,在我看来,使用这种具体的继承是不必要的。我想迁移为使用抽象基类。

使事情变得复杂的是,我的站点处于活动状态,并且用户输入了数据。因此,在整个过渡过程中,我需要保持所有数据不变。

我将举一个具体的例子:

之前:

app1 / models.py:

class Model1(base_app.models.BaseModel):
    field1 = models.CharField(max_length=1000)
    field2 = models.CharField(max_length=1000)

app2 / models.py:

class Model2(base_app.models.BaseModel):
    field1 = models.CharField(max_length=1000)
    field2 = models.CharField(max_length=1000)

base_app / models.py:

class BaseModel(models.Model):
    user = models.ForeignKey(User)
    another_field = models.CharField(max_length=1000)

后:

app1 / models.py:

class Model1(base_app.models.BaseModel):
    field1 = models.CharField(max_length=1000)
    field2 = models.CharField(max_length=1000)

app2 / models.py:

class Model2(base_app.models.BaseModel):
    field1 = models.CharField(max_length=1000)
    field2 = models.CharField(max_length=1000)

base_app / models.py:

class BaseModel(models.Model):
    user = models.ForeignKey(User)
    another_field = models.CharField(max_length=1000)

    class Meta:
        abstract = True

现在,我的计划是先将添加abstract = True到BaseModel。然后,对于每个使用的模型,一次使用BaseModel一个:

  • 使用south来迁移数据库并使用–auto标志创建此迁移
  • 使用南方数据迁移。例如,我将遍历Model1中的每个对象,以在BaseModel中获取具有相同pk的对象,并将BaseModel对象的每个字段的值复制到Model1对象。

那么首先,这行得通吗?其次,还有更好的方法吗?

更新:

我的最终解决方案在此处详细介绍:

http://www.markliu.me/2011/aug/23/migrating-a-django-postgres-db-from-
concrete-inhe/


问题答案:
  1. 添加NewBaseModel,我们使用不同的名称,因此它不会与当前的非抽象名称冲突(South实际上会删除BaseModel)。

    class NewBaseModel(models.Model):
    user = models.ForeignKey(User)
    another_field = models.CharField(max_length=1000)
    
    class Meta:
        abstract = True
    
  2. 将Model1和Model2设置为继承自NewBaseModel

  3. 运行schemamigration –auto,将向Model1和Model2添加2个新字段

  4. 运行datamigration –empty并从BaseModel中的值填充新字段
  5. 加载生产数据库并仔细检查所有已正确迁移的内容
  6. 删除BaseModel并将NewBaseModel重命名为BaseModel
  7. 运行schemamigration –auto(这 应该 工作;))
  8. 部署!

注意:迁移以使用模型架构的当前状态时,请使用 orm 变量。