如何删除引用到对象的所有嵌套对象?

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 中的引用,如何删除对象?

如何验证和删除 JSON 对象的嵌套节点

如何删除 Graphene Django 突变查询(中继)中的嵌套输入对象?

如何从对象中递归删除子对象?

如何在 mongodb 中自动删除对象 ID 引用