使用Django South从具体继承转向抽象继承 [英] Using Django South to move from concrete inheritance to abstract inheritance
问题描述
使这个复杂的事情是我的网站是活的,我有用户输入的数据。因此,我需要在整个过渡期间保持所有的数据完整。
我将举一个更具体的例子:
之前:
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.mode ls.BaseModel):
field1 = models.CharField(max_length = 1000)
field2 = models.CharField(max_length = 1000)
app2 / models.py:
class Model2(base_app.models.BaseModel):
pre>
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
的每个模型,一次一个:
- 使用迁移数据库并使用--auto标志创建此迁移
- 使用南方数据迁移。例如,我将循环遍历Model1中的每个对象,以获取具有相同pk的BaseModel中的对象,并将BaseModel对象的每个字段的值复制到Model1对象。
首先,这个工作吗?第二,有没有更好的方法呢?
更新:
我的最终解决方案在此详细描述:
http://www.markliu.me/2011/aug/23/migrating-a-django-postgres-db-from-concrete-inhe /
-
添加NewBaseModel,我们使用不同的名称,与当前非抽象的冲突(南方实际上将删除BaseModel)否则
类NewBaseModel(models.Model):
user = models.ForeignKey(User)
another_field = models.CharField(max_length = 1000)
class Meta:
abstract = True
-
将Model1和Model2设置为继承自NewBaseModel
- 运行模式迁移--auto,将添加2个新字段到Model1和Model2
- 运行d atamigration - 空,并从BaseModel中的值填充新字段
- 加载生产数据库并仔细检查正确迁移的所有内容
- 删除BaseModel并将NewBaseModel重命名为BaseModel
- 运行schemamigration --auto(这个
应该 work;)) - 部署!
注意:迁移时使用 orm 变量来使用模型模式的当前状态。
I have an existing Django project that has several models using concrete inheritance of a base class. After closer consideration, and after reading about what people like Jacob Kaplan-Moss have to say about it, using this concrete inheritance is unnecessary in my case. I would like to migrate to using an abstract base class instead.
The thing that makes this complicated is that my site is live and I have user entered data. Thus, I'll need to keep all my data intact throughout this transition.
I'll give an example to be more concrete:
Before:
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)
After:
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
Right now, my plan is to first add the abstract = True
to the BaseModel. Then,for each model that uses BaseModel
, one at a time:
- Use south to migrate the database and create this migration using the --auto flag
- Use a south data migration. For instance, I would loop through each object in Model1 to fetch the object in BaseModel that has the same pk and copy the values for each field of the BaseModel object to the Model1 object.
So first, will this work? And second, is there a better way to do this?
Update:
My final solution is described in detail here:
http://www.markliu.me/2011/aug/23/migrating-a-django-postgres-db-from-concrete-inhe/
Add NewBaseModel, we use different name so it doesn't conflict with current non-abstract one (South would actually delete BaseModel otherwise).
class NewBaseModel(models.Model): user = models.ForeignKey(User) another_field = models.CharField(max_length=1000) class Meta: abstract = True
Set Model1 and Model2 to inherit from NewBaseModel
- Run schemamigration --auto, 2 new fields will be added to Model1 and Model2
- Run datamigration --empty and fill new fields from values in BaseModel
- Load production db and double check everything migrated correctly
- Remove BaseModel and rename NewBaseModel to BaseModel
- Run schemamigration --auto (this should work ;) )
- Deploy!
NOTE: Use orm variable when migrating to use current state of your model schema.
这篇关于使用Django South从具体继承转向抽象继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!