我有一個傳統的Django模型,它的實現對我的口味有點特定。我想生成這個模型的更多特定的子類來處理不同的場景,但是想爲一些常見的字段和方法保留一個通用的基類。樣品模型如下:從父類到子類的南數據遷移clobbers父數據
class SomeOldClass(models.Model):
sharedField1 = models.CharField('This is a shared field1', max_length=10)
sharedField2 = models.CharField('This is a shared field2', max_length=10)
specificField1 = models.CharField('This is a specific field1', max_length=10)
最後,我想打破這股sharedField1和sharedField2 SomeOldClass的子類。
class SomeOldSubclass(SomeOldClass):
specificField1_new = models.CharField('This is a specific field1', max_length=10)
注意由於錯誤創建一個字段具有相同名稱作爲家長追加到specificField1在SomeOldSubclass的_new。
我的計劃是有三個南腳本:
- 架構遷移來建立新的 app_someoldsubclass表
- 數據 遷移腳本從 app_someoldclass.specificField1複製值 app_someoldsubclass.specificField1_new
- 模式遷移丟棄 來自app_someoldclass的specificField1 並將specificField1_new重命名爲 specificField1在 app_someoldsubclass
當然,我可以將這些腳本組合成一個遷移腳本,但我承擔。
隨着類如上面所定義,我創建的模式遷移腳本:./manage.py schemamigration app --auto
然後,我創建了一個empy數據遷移腳本:./manage.py datamigration app copy_values
我修改了數據遷移腳本在我的向前添加此方法:
def forwards(self, orm):
"Write your forwards methods here."
for soc in orm.SomeOldClass.objects.all():
sosc = orm.SomeOldSubclass.objects.get_or_create(someoldclass_ptr=soc, specificField_new=soc.specificField1)
注意,因爲從SomeOldSubclass繼承SomeOldClass,我創建了一個新的SomeOldSubclass實例SomeOldClass的每個實例,並更新someoldclass_ptr的d specificField1_new值。
如預期的那樣,運行遷移爲app_someoldclass中的每一行在app_someoldsubclass中創建一個新行,其中specificField1_new的值與app_someoldclass.specificField1中的值相同。但是,現在app_someold類中的所有字段都已被完全清除。如果我要爲現有ID創建SomeOldClass模型的實例,則sharedField1
將爲None
。實際上,唯一仍然有效的值是app_someoldclass中的id。
事實上,app_someoldclass保留其原始值的唯一方法就是修改我前進的方法如下:
def forwards(self, orm):
"Write your forwards methods here."
for soc in orm.SomeOldClass.objects.all():
sosc = orm.SomeOldSubclass.objects.get_or_create(someoldclass_ptr=soc, specificField_new=soc.specificField1)
soc.save()
(注此外soc.save()的)
這是預期的行爲?我會假設因爲我沒有修改由Soc對象表示的SomeOldClass的實例,所以不需要再次保存它。即使我沒有保存它,我當然也不會期望數據被破壞。
這是南方嗎? Django的東西?用戶錯誤的事情?
也許我失去了一些東西,但get_or_create將返回我,我要找的對象實例我傳遞的參數相匹配,創建一個,如果它不存在。我一直在使用get_or_create的原因是由於新創建的SomeOldSubclass類型的對象可以在原始模式遷移和隨後的數據遷移之間創建。 – Roger
此外,我看到的問題是SomeOldClass(我只用於讀取值的實例)正在擦除其數據,同時遍歷orm.SomeOldClass.objects.all()的列表,除非我明確地保存SomeOldClass實例。對我而言,如果我沒有對它們進行任何明確的修改,那麼在數據遷移期間應該以任何方式修改這些實例,這似乎很奇怪。 – Roger