2013-05-26 22 views
0

我有以下型號:
Django的負載對象是重複

class Car(models.Model): 
id = models.AutoField(primary_key=True) 
slug = models.CharField(max_length=128L, unique=True, blank=True) 
name = models.CharField(max_length=128L, blank=True) 
model_slug = models.CharField(max_length=128L, unique=True, blank=True) 
... 

每當我從一個XML文件中獲取的Car列表,其中一些出現多次
(如果我試圖保存,我得到
IntegrityError(1062, "Duplicate entry 'car-slug' for key 'slug'")

我希望它加載現有的汽車(或更新它,以較輕者爲準),以防萬一有一個重複的錯誤。
但我希望它足夠通用,以便它可以用於model_slug(或生成該錯誤的任何唯一字段)。

+0

我最後寫https://gist.github.com/kidsil/5658666 – Asaf

回答

0

我結束了編寫自定義的模型保存(讓我的代碼並沒有改變,只是型號):

def save(self, *args, **kwargs): 
    try: 
     super(Car, self).save(*args, **kwargs) 
    except IntegrityError, e: 
     existing_object = Car.objects.get(slug=self.slug) 
     self = existing_object 
     super(Car, self).save(*args, **kwargs) 
     return existing_object.id 

現在我返回對象的ID分配它,因此保存()命令看起來是這樣的:

the_id = generic_object.save() #e.g. Car 
if the_id: 
    generic_object.id = the_id 
1

您需要get_or_create

car,created = Car.objects.get_or_create(slug='car-slug') 
if created: 
    print 'New car was created' 
    car.slug = 'new-car-slug' 
else: 
    # do whatever needs to be done here 
    # with the existing car object, which will 
    # be car 
    # car.name = 'new name' 

car.save() 

您提供get_or_create無論參數,它會使用這些搜索現有記錄的模型。


假設你不知道字段組合會觸發重複。簡單的方法是找出模型中的哪些字段具有該限制(即unique=True)。您可以從模型中反省這些信息,或者更簡單的方法是將這些字段傳遞給get_or_create

第一步是將XML領域和模型的字段之間創建一個映射:

xml_lookup = {} 
xml_lookup = {'CAR-SLUG': 'slug'} # etc. etc. 

可以填充這將各個領域,如果你想要的,但我的建議是隻有那些字段來填充它是對他們有一個獨特的約束。

接下來,當你正在分析你的XML,填充字典的每個記錄,映射每個字段:

for row in xml_file: 
    lookup_dict = {} 
    lookup_dict[xml_lookup[row['tag']] = row['value'] # Or something similar 
    car, created = Car.objects.get_or_create(**lookup_dict) 
    if created: 
     # Nothing matched, a new record was created 
     # Any any logic you need here 
    else: 
     # Existing record matched the search parameters 
     # Change/update whatever field to prevent the IntegrityError 
     car.model_slug = row['MODEL_SLUG'] 
     # Set/update fields as required 
    car.save() # Save the modified object 
+0

可悲的是這個解決方案是不適合我足夠的通用性,因爲蛞蝓可能是不同的,但model_slug是一樣的在這種情況下,它仍然會引發誠信錯誤。我試圖儘可能沒有具體(沒有字段名稱) – Asaf

+0

只需直接添加和修改過濾器?唯一的另一種方式是讓你把所有東西都包裝在一起,這真的很愚蠢。所以你要做的是將你的XML邏輯封裝在這段代碼中。每當你從XML文件中讀取一條記錄時,檢查一個對象是否存在'slug'或者'model-slug' - 如果它存在就檢索它,或者如果它不存在則創建一個新的對象(這就是' get_or_create'會做);因此你會避免完整性錯誤。你也可以使用'** dict'來摔打,然後搜索模型中的_every_字段。 –

0

可以先篩選內存中的重複車條目,然後調用創建新的項目,如,

uniq_attrs = ['slug', 'model_slug', ...] 
existed_attrs = set() 
for car in car_list: 
    # skip the duplicates 
    if any([(attr, car[attr]) in existed_attrs for attr in uniq_attrs): 
     continue 
    uniq_attrs.update([(attr, car[attr]) for attr in uniq_attrs]) 

    # save the new car to db 
    Car.objects.save(....) 

,或者你可以嘗試在獨特領域get_or_create然後保存等attribues與模型保存,例如,

for car in car_list: 
    attr_dict = {attr:car[attr] for attr in uniq_attrs} 
    car, created = Car.objects.get_or_create(**attr_dict) 

    # already created before 
    if created: 
     continue 

    # save other attributes 
    car.set(...) 
    car.set(...) 
    car.save()