2011-06-21 30 views
3

我有一個傳統的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。

我的計劃是有三個南腳本:

  1. 架構遷移來建立新的 app_someoldsubclass表
  2. 數據 遷移腳本從 app_someoldclass.specificField1複製值 app_someoldsubclass.specificField1_new
  3. 模式遷移丟棄 來自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的東西?用戶錯誤的事情?

回答

0

問題出在get_or_create。它的工作方式與你期望的不同。

有兩種方法來解決這個問題:

  • 不使用get_or_create,或
  • 調試問題

要調試的問題,您應該:

  • 閱讀get_or_create文檔
  • 也許讀取get_o r_create實施
  • 看看生產的SQL語句
+0

也許我失去了一些東西,但get_or_create將返回我,我要找的對象實例我傳遞的參數相匹配,創建一個,如果它不存在。我一直在使用get_or_create的原因是由於新創建的SomeOldSubclass類型的對象可以在原始模式遷移和隨後的數據遷移之間創建。 – Roger

+0

此外,我看到的問題是SomeOldClass(我只用於讀取值的實例)正在擦除其數據,同時遍歷orm.SomeOldClass.objects.all()的列表,除非我明確地保存SomeOldClass實例。對我而言,如果我沒有對它們進行任何明確的修改,那麼在數據遷移期間應該以任何方式修改這些實例,這似乎很奇怪。 – Roger

0

的問題是不是在南方,它在你使用的子類

當您保存一個子類,它設置在從數據庫中的所有值的領域。 您的sosc對象已使用其默認值的所有父派生字段創建。

保存子類時,它將覆蓋父項。 然後,soc.save()再次將父項重置爲其原始值。

https://code.djangoproject.com/ticket/7623