【问题标题】:django - query and delete GenericForeignKeydjango - 查询和删除 GenericForeignKey
【发布时间】:2014-04-09 20:08:27
【问题描述】:

假设,这是一个模型作为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!

所以,我想,这不是这样做的方式。请帮我解决这个问题。谢谢!

【问题讨论】:

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


    【解决方案1】:

    这是因为GenericForeignKey 中实际上可能存在重复的 ID。例如。如果你有一个Photo 模型和一个Article 模型,两者都关联了一个Entry,那么照片的主键可以和文章的主键相同,object_ids 将相同.这就是为什么你需要一个 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')
    

    【讨论】:

    • 我没有看到使用 GenericRelation 的方法有效。相反,删除后,我仍然拥有具有较早 .object_id 的 Entry 实例。并且 .content_object 是无。为什么没有删除Entry实例?我做错了什么?
    • 所以我知道我的情况的原因。我处理一些公司代码。 GenericRelation 属性不是在模型内部添加的,而是在 apps.py 中使用 .ready() 方法整体添加的。这是我们的错误,因为它来晚了。反向链接工作正常(可能它们是在 django 中使用惰性定义处理的),但级联删除会默默地失败。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 2012-08-11
    • 2011-06-01
    相关资源
    最近更新 更多