2013-08-29 56 views
7

如前所述被用於OneToOne關係到其他模型的模型自動創建here對象。因此,如果我將具有O2O的Model1與Model2相關聯,並且將創建pk = 1的Model2的對象,那麼將自動創建具有model2_id = 1的Model1的對象。然後,如果不幸將數據從數據庫轉儲到json,我將爲這些對象創建兩條記錄。如果我會嘗試將此數據加載到數據庫與loaddata - 它會失敗,因爲Model2的對象將被創建兩次,這將導致唯一索引衝突和IntegrityError
有沒有人爲此找到理智的解決方案?Django的燈具和OneToOneField

p.s.
我使用Django 1.3.7

+0

您是否找到了解決方案? –

+0

如果你不得不這樣做,我建議更新django – Alp

+4

不要以爲轉儲數據中會有多個對象或多次創建。你能告訴我們什麼轉儲數據給你?還有loaddata的錯誤? – Rohan

回答

0

你可能最終使用南,這使得數據遷移既簡單又強大:

http://south.readthedocs.org/en/latest/about.html

使用Django 1.6的到來,一個新的migrations module將取代舊的數據庫命令並使南方過時。

+0

遷徙正與1.7 ...但我不認爲他們在這種情況下(南方都不會)幫助 – OBu

+0

你能告訴我一個事實的來源,遷移是與1.7來? – Alp

+1

我們在https://code.djangoproject.com/ticket/21142進行了一些討論,並且在http://www.kickstarter.com/projects/andrewgodwin/schema上有一個kickstarter項目,聲明來自南方作者。 -migrations換Django的。我在1.7版本中測試了它,但是由於第一個鏈接中提到的錯誤沒有完全解決,但它並沒有爲我工作。 – OBu

4

我沒有類似的東西,notwith JSON但與XML和我的Django是1.7,所以也許它不爲你工作。

  1. 當您引用序列化對象時,可以使用natural keys。如果索引已被其他對象使用,這將防止混合項目。
  2. 您可以使用dependencies定義序列化(和反序列化,因此)的順序。

也許類似的帖子,如this one也有幫助。

+0

當我寫這篇文章的時候,Django還沒有發佈1.6,所以我認爲你可能錯誤地輸入了Django的版本號 –

+0

不,我確實使用了最新的alpha版本1.7 – OBu

+1

順便說一句:1.6現在不存在! – OBu

0

事實上,如果你想使用諸如dumpdataloaddata命令,例如備份和數據庫中的恢復選擇對象O2O的關係可能很麻煩。

我們的軟件存在類似的問題,我發現可能的工作解決方案是覆蓋django.core.serializers.base.DeserializedObject上的save()方法,以便在「double」對象保存之前真正獲得句柄。此時,您可能會決定丟棄由Django創建的默認O2O關係,並讓框架保存新的關係或使用XML或JSON文件中存儲的值更新它。

你不得不把覆蓋方法某處雖然執行loaddata命令之前Django的回升。一種可能性是創建自己的命令,然後調用loaddata。在命令模塊中,您安裝覆蓋。關於此解決方案的以下詳細信息是隱含的:

  • 經過Django 1.8測試。X
  • 我們的O2O領域連接到Django的User模型
  • 爲了簡化本例中的份上,我會打電話給所連接的O2O領域Attached

# Overrides deserialization to affect OneToOneFields for Users correctly 
import django.core.serializers.base 
from django.contrib.auth.models import User 
from your.attached.models import Attached #model with O2O field to User 

_original_save = django.core.serializers.base.DeserializedObject.save 

def save(self, *args, **kwargs): 

    if isinstance(self.object, Attached): 
    # if the user in question has an attached object, delete it 
    user = User.objects.get(pk=self.object.user_id) 
    if hasattr(user, 'attached'): user.attached.delete() 

    # use the built-in function for all other cases 
    _original_save(self, *args, **kwargs) 

django.core.serializers.base.DeserializedObject.save = save 

您可以修改代碼上面,而不是刪除現有對象,更新它,如果你在if hasattr(...)條款,避免刪除,更新的值來自的現有對象您的序列化對象並跳過致電_original_save()的呼叫。它會使代碼與模型綁定更多,因爲您可能必須定義要在現有對象上更新哪些字段。上面顯示的解決方案沒有假設模型的內容。