2014-03-06 55 views
0

假設,這是一個模型作爲外鍵的ContentTypeDjango的 - 查詢和刪除GenericForeignKey

class Photo(models.Model): 
    user = models.ForeignKey(User) 
    description = models.TextField() 
    image = models.ImageField(upload_to=get_upload_file_name) 
    pub_date = models.DateTimeField(auto_now=True, auto_now_add=False) 

這是ContentType模型:

class Entry(models.Model): 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    pub_date = models.DateTimeField() 
    content_object = generic.GenericForeignKey('content_type','object_id') 

每當一個新的照片或狀態創建了新的Entry。現在,我想要的是,每當我刪除一個Photo/Status的實例時,我想從Entry中刪除與該照片/狀態相關的對象?我怎麼做?

我嘗試這樣做:

def delete_entry(sender, **kwargs): 
    instance = kwargs['instance'] 
    try: 
     si = Entry.objects.get(object_id=instance.id) 
     si.delete() 
    except Entry.DoesNotExist: 
     si = None 

有時它的工作。但再次有時我得到一個錯誤:

MultipleObjectsReturned 
get() returned more than one Entry -- it returned 2! 

所以,我想,那是不是這樣做的方式。請幫我解決這個問題。謝謝!

回答

1

這是因爲在GenericForeignKey中實際上可能存在重複ID。例如。如果您有一個Photo模型和一個Article模型,並且它們都與Entry相關聯,則該照片的主鍵可以與該文章的主鍵具有相同的值,並且object_id將會相同。這就是爲什麼你需要一個content_type和一個object_id開始。

要獲得正確的對象,您需要檢查類型和ID。

from django.contrib.contenttypes.models import ContentType 

def delete_entry(sender, instance, **kwargs): 
    content_type = ContentType.objects.get_for_model(instance) 
    entry = Entry.objects.get(content_type=content_type, 
           object_id=instance.id) 
    entry.delete() 

另一種方式來完成,這是使用GenericRelation(見documentation)。這是GenericForeignKey的反向關係。每當有GenericRelation一個對象被刪除,這個瀑布所提供的模型的任何物體與GenericForeignKey指向該實例:

from django.contrib.contenttypes.generic import GenericRelation 

class Photo(models.Model): 
    ... 
    entries = GenericRelation(Entry, content_type_field='content_type', 
           object_id_field='object_id') 
+0

好!這工作!謝謝。 – Kakar