django - 查询并删除GenericForeignKey

时间:2014-03-06 22:12:13

标签: django django-queryset django-orm django-contenttypes

假设这是一个模型作为ContentType的外键:

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 个答案:

答案 0 :(得分:1)

那是因为GenericForeignKey实际上可能存在重复的ID。例如。如果您有Photo模型和Article模型,两者都与Entry相关联,则照片的主键可以与文章的主键相同,而{{{ 1}} s将是相同的。这就是为什么你需要开始object_idcontent_type

要获得正确的对象,您需要检查类型和ID。

object_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() (请参阅documentation)。这是GenericRelation的反向关系。每当删除具有GenericForeignKey的对象时,这将与所提供模型的任何对象级联,并使用GenericRelation指向该实例:

GenericForeignKey