2012-03-01 31 views
2

如何加載Django夾具,以便通過自然鍵引用的模型不會與預先存在的記錄發生衝突?加載包含自然鍵的Django夾具

我試圖加載這樣的燈具,但我從我的MySQL後端得到IntegrityErrors,抱怨Django試圖插入重複記錄,這沒有任何意義。

正如我理解Django的自然關鍵特性,爲了完全支持dumpdata和loaddata的使用,您需要在模型的管理器中定義模型中的natural_key方法和get_by_natural_key方法。

因此,舉例來說,我有兩個型號:

class PersonManager(models.Manager): 
    def get_by_natural_key(self, name): 
     return self.get(name=name) 

class Person(models.Model): 

    objects = PersonManager() 

    name = models.CharField(max_length=255, unique=True) 

    def natural_key(self): 
     return (self.name,) 

class BookManager(models.Manager): 
    def get_by_natural_key(self, title, *person_key): 
     person = Person.objects.get_by_natural_key(*person_key) 
     return self.get(title=title, person=person) 

class Book(models.Model): 

    objects = BookManager() 

    author = models.ForeignKey(Person) 

    title = models.CharField(max_length=255) 

    def natural_key(self): 
     return (self.title,) + self.author.natural_key() 
    natural_key.dependencies = ['myapp.Person'] 

我的測試數據庫已經包含了樣本人物和書的記錄,這是我用來生成夾具:

[ 
    { 
     "pk": null, 
     "model": "myapp.person", 
     "fields": { 
      "name": "bob" 
     } 
    }, 
    { 
     "pk": null, 
     "model": "myapp.book", 
     "fields": { 
      "author": [ 
       "bob" 
      ], 
      "title": "bob's book", 
     } 
    } 
] 

我想以便能夠使用該夾具並將其加載到我的數據庫的任何實例中以重新創建記錄,而不管它們是否已經存在於數據庫中。

然而,當我運行python manage.py loaddata myfixture.json我得到的錯誤:

IntegrityError: (1062, "Duplicate entry '1-1' for key 'myapp_person_name_uniq'") 

爲什麼Django的試圖重新創建人員記錄,而不是重複使用一個已經存在?

+0

您是否使用帶有--natural選項的dumpdata? – xblitz 2013-08-23 13:00:18

回答

1

原來這個解決方案需要Django的loaddata命令的一個非常小的補丁。由於Django的開發人員不太可能接受這樣的補丁,因此我在包中提供了各種Django管理相關增強的forked it

關鍵代碼更改(loaddatanaturally.py的第189-201行)僅涉及調用get_natural_key()來查找遍歷反序列化對象的循環內的任何現有pk。