首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么我的GenericForeignKey在删除时不能级联?

为什么我的GenericForeignKey在删除时不能级联?
EN

Stack Overflow用户
提问于 2011-07-24 04:12:53
回答 3查看 6.7K关注 0票数 24

我正在创建一个自定义注释系统,它可以使用contenttypes GenericForeignKey将注释附加到任何模型。

代码语言:javascript
复制
class Comment(models.Model):
    body = models.TextField(verbose_name='Comment')
    user = models.ForeignKey(User)
    parent = models.ForeignKey('self', null=True, blank=True)
    created = models.DateTimeField(auto_now_add=True)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

我的理解是,当注释附加到的模型被删除时,删除应该级联并删除注释。

不幸的是,这并没有发生,我被难住了。有没有什么常见的原因会改变默认的删除行为?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-07-24 04:49:41

不,文档上没有这么说。它说的是,如果你在一个模型上定义了一个GenericRelation --即GenericForeignKey的反面--那么当带有通用FK的项被删除时,带有GenericRelation的项也会被删除。

与ForeignKey不同,GenericForeignKey不接受on_delete参数来自定义此行为;如果需要,只需不使用GenericRelation即可避免级联删除,并可通过pre_delete信号提供替代行为。

票数 32
EN

Stack Overflow用户

发布于 2018-05-04 19:59:41

我意识到这是一个非常的老问题,所以事情可能与被问到这个问题时不同,但今天早上被接受的答案让我陷入了困境,因此我想把这个留在这里,以防后代分享我的痛苦。

从文档中:

还请注意,如果您删除一个具有GenericRelation的对象,则任何具有指向它的GenericForeignKey的对象也将被删除。在上面的例子中,这意味着如果一个书签对象被删除,任何指向它的TaggedItem对象都会同时被删除。

这与公认的答案相反。想象一下:

代码语言:javascript
复制
class Comment(models.Model):
    body = models.TextField(verbose_name='Comment')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

class Post(models.Model):
    comment = GenericRelation(Comment)

在上面的例子中,如果您的Comment对象有一个指向Post对象的通用外键,那么当Post对象被删除时,指向它的任何Comment对象也将被删除。

这是预期的行为,其操作方式与正常的ForeignKey相同。使用上面的相同示例,如果删除了Comment对象所指向的User对象,那么Comment也将被删除。

如果你碰巧遇到这个问题,因为你需要相反的行为,即当你删除评论时,帖子也会被删除,那么你可能需要使用signals的力量。

票数 12
EN

Stack Overflow用户

发布于 2018-08-10 17:30:22

除了前面的答案-如果你有更复杂的结构和类似GenericOneToOne的东西(这在Django中不是直接存在的):

代码语言:javascript
复制
class Post(models.Model)
    title = models.CharField(max_length=100)

class Comment(models.Model):
    post = models.ForeignKey(Post)
    body = models.TextField(verbose_name='Comment')
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    class Meta:
        # Constrain equals to OneToOne relation.
        unique_together = ('content_type', 'object_id')

class Author(models.Model):
    comment = GenericRelation(Comment)
    name = models.CharField(max_length=100)

如果你想删除Post,并确保CommentAuthor也被删除,你需要编写定制的post_delete信号:

代码语言:javascript
复制
from django.db.models.signals import post_delete
from django.dispatch import receiver

@receiver(post_delete, sender=Comment, dispatch_uid='delete_comment_content_object')
def delete_comment_content_object(sender, instance, using, **kwargs):
    instance.content_object.delete()

如果像这样覆盖Commentdelete方法:

代码语言:javascript
复制
def delete(self, *args, **kwargs):
    self.content_object.delete()
    super().delete(args, kwargs)

如果您删除,它将删除Author only。如果删除PostAuthor对象将保留在数据库中。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6803018

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档