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
答案 0 :(得分:8)
您正在将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()