如何删除引用到对象的所有嵌套对象?
Posted
技术标签:
【中文标题】如何删除引用到对象的所有嵌套对象?【英文标题】:How to delete all nested objects referenced to an object? 【发布时间】:2019-03-28 08:51:05 【问题描述】:我有一个模型在几个模型中设置为外键。现在从模型中删除任何对象都会抛出 ProtectedError 如果它在任何这些模型中被引用。我想让用户在一次操作中删除所有受保护对象的对象。
我可以通过调用删除第一层保护对象
....
except ProtectedError as e
e.protected_objects.delete()
....
但是当protected_objects
拥有自己的受保护对象时,操作失败并抛出另一个第二层ProtectedError
。我想要实现的是,删除所有受保护的对象,不加区别地存在于哪一层。我知道执行这可能是一项危险的操作。但是我可以在没有复杂解决方案的情况下实现这一目标吗?提前致谢。
源代码,我正在尝试执行ajax操作:
try:
obj_list = model.objects.filter(pk__in=pk_list)
log_deletion(request, obj_list, message='Record Deleted')
obj_list.delete()
return JsonResponse('success': True, 'status_message': '0 record(s) has been deleted successfully.'.format(len(pk_list)))
except ProtectedError as e:
e.protected_objects.delete()
return JsonResponse('success': False, 'status_message': 'This operation cannot be executed. One or more objects are in use.')
【问题讨论】:
你可以使用循环吗? 你能明确显示...
吗?
@MadPhysicist 我已经添加了源代码。循环可以是一个解决方案,但我需要显示与对象相关的所有层中的所有受保护对象。这可能吗?
是否有任何东西阻止您在每次迭代中记录?
【参考方案1】:
一般来说,你可以使用循环:
...
except ProtectedError as e:
obj = e.protected_objects
while True:
try:
obj.delete()
except ProtectedError as e:
obj = e.protected_objects
else:
break
...
要记录错误发生在哪一层,您可以添加一个计数器:
from itertools import count
obj_list = model.objects.filter(pk__in=pk_list)
for layer in count():
try:
log_deletion(request, obj_list, message='Record Deleted in layer '.format(layer))
obj_list.delete()
except ProtectedError as e:
obj_list = e.protected_objects
else:
if layer == 0:
return JsonResponse('success': True, 'status_message': '0 record(s) has been deleted successfully.'.format(len(pk_list)))
else:
return JsonResponse('success': False, 'status_message': 'This operation cannot be executed. One or more objects are in use.')
【讨论】:
【参考方案2】:您似乎不想在外键定义上使用on_delete=models.PROTECT
。您是否考虑过 changing the on delete 使用 CASCADE
代替?如果使用级联,则无需遍历依赖项即可先删除它们。
而不是:
class OtherModel(models.Model):
link = models.ForeignKey("Link", on_delete=models.PROTECT)
您可以像这样定义模型:
class OtherModel(models.Model):
link = models.ForeignKey("Link", on_delete=models.CASCADE)
当从管理员中删除使用CASCADE
的模型时,将显示一个中间页面,其中列出了所有也将被删除的依赖对象。
【讨论】:
目前,我们使用 models.PROTECT,因为我们需要让用户知道我们正在删除哪些相关对象,并且此过程会提示确认。以上是关于如何删除引用到对象的所有嵌套对象?的主要内容,如果未能解决你的问题,请参考以下文章
考虑到 Mongoose Node.js 中的引用,如何删除对象?