GenericForeignKey和on_delete = models.PROTECT

时间:2016-09-15 09:16:42

标签: django django-models

Django 1.10

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

在shell中:

Comment.objects.all()
<QuerySet []>

然后我删除了帧实例(调用FrameDelete)。和

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')

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

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

StackView

1 个答案:

答案 0 :(得分:8)

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

documentation states

  

与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()