gpt4 book ai didi

django - 强制对 Django 模型进行级联删除

转载 作者:行者123 更新时间:2023-12-05 02:09:38 29 4
gpt4 key购买 nike

我有一个带有标记为 deletion.PROTECT 的外键关系的 Django 模型,我可以接受这种行为,因为在大多数情况下模型都应该这样做。

但是,对于那些我需要执行“硬删除”(即用户想要删除他们的帐户)的模型,有一个用例。在那种情况下,我真的希望一切都表现得像 CASCADE,而不必手动删除每个外键关系。有没有办法干净地做到这一点?在理想情况下,model.delete() 调用将采用类似于 force_cascade=True 的参数。

最佳答案

由于 django 还创建了具有 PROTECTED 关系的数据库,因此您需要自己手动进行级联删除。否则数据库本身将禁止删除。

Django 的 ORM 可以帮助您解决这个问题,您唯一需要做的就是递归查找所有对用户的引用并以相反的顺序删除它们。手动执行此操作也是一个优势,因为您可能希望用替代项(即虚拟的“已删除用户”)替换某些出现的用户。我可以想到留言板上的评论,即使用户删除了他们的帐户,也应该保留这些评论。

要查找指向当前用户的关系并将它们替换为幽灵用户,您可以使用以下代码段。

from typing import List
from django.contrib.auth import get_user_model
from django.db.models import Model
from django.db.models.fields.reverse_related import (
ManyToOneRel,
ForeignObjectRel,
)

User = get_user_model()


def get_all_relations(model: Model) -> List[ForeignObjectRel]:
"""
Return all Many to One Relation to point to the given model
"""
result: List[ForeignObjectRel] = []
for field in model._meta.get_fields(include_hidden=True):
if isinstance(field, ManyToOneRel):
result.append(field)
return result


def print_updated(name, number):
"""
Simple Debug function
"""
if number > 0:
print(f" Update {number} {name}")


def delete_user_and_replace_with_substitute(user_to_delete: User):
"""
Replace all relations to user with fake replacement user
:param user_to_delete: the user to delete
"""
replacement_user: User = User.object.get(pk=0) # define your replacement user
for field in get_all_relations(user_to_delete):
field: ManyToOneRel
target_model: Model = field.related_model
target_field: str = field.remote_field.name
updated: int = target_model.objects.filter(
**{target_field: user_to_delete}
).update(**{target_field: replacement_user})
print_updated(target_model._meta.verbose_name, updated)
user_to_delete.delete()

对于真正的删除,只需将 .update(...) 函数替换为 .delete() 调用(不要忘记递归地查找 protected 关系之前,如果需要的话)

可能还有一个我不知道的与postgresql相关的解决方案。给定的解决方案是独立于数据库的。

一般来说,保护每个关系以防止意外删除重要的数据库条目并小心手动删除是个好主意。

关于django - 强制对 Django 模型进行级联删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59668809/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com