GenericForeignKey和on_delete = models.PROTECT

Mic*_*ael 1 django django-models

Django 1.10

说,我有一个Frame的实例和两个注释.关键时刻:评论模型中的on_delete = models.PROTECT.

在shell中:

Comment.objects.all() 
<QuerySet [<Comment: Some comment.>, <Comment:
Second comment.>]
Run Code Online (Sandbox Code Playgroud)

然后我删除帧实例(调用FrameDelete).和:

Comment.objects.all()
<QuerySet []>
Run Code Online (Sandbox Code Playgroud)

空.删除了所有评论.而models.PROTECT没有帮助.

好吧,我无法让它捕获IntegrityError.你能告诉我它是否可能以及如何做?

class FrameDelete(IntegrityErrorMixin, DeleteView):
    model = Frame

class IntegrityErrorMixin():
    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        success_url = self.get_success_url()
        try:
            self.object.delete()
        except IntegrityError as err:
            raise PermissionDenied

        return HttpResponseRedirect(success_url)

class Frame(models.Model):
    .....
    comments = GenericRelation(Comment)

class Comment(models.Model):
    date = models.DateTimeField(null=False,
                            blank=False,
                            auto_now_add=True)

    author = models.ForeignKey(User, on_delete=models.PROTECT)
    body = models.TextField(blank=False,
                            null=False,
                            default="",
                            verbose_name = "",) # Empty. No need to show the verbose_name on the form.

    content_type = models.ForeignKey(ContentType, on_delete=models.PROTECT)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
Run Code Online (Sandbox Code Playgroud)

knb*_*nbk 9

你要传递on_delete=models.PROTECT给外键ContentType.这只会在您删除内容类型时生效,而不是在删除注释时生效.

文档状态:

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

因此,为了模拟行为models.PROTECT,pre_delete如果存在任何相关注释,则需要附加引发异常的信号,如下所示:

from django.db.models import ProtectedError, signals

@receiver(signals.pre_delete, Frame)
def protect_delete(sender, instance, **kwargs):
    if instance.comments.exists():
        raise ProtectedError()
Run Code Online (Sandbox Code Playgroud)