【问题标题】:Django check if model has related object before deleting the modelDjango在删除模型之前检查模型是否有相关对象
【发布时间】:2016-09-27 14:40:33
【问题描述】:

在寻找一种方法来检查是否可以在 django 中删除模型实例后,我发现了很多选项,但没有一个按预期工作。希望这个解决方案能有所帮助。

让我们从创建一个可以被其他模型继承的抽象模型类开始

class ModelIsDeletable(models.Model):
    name = models.CharField(max_length=200, blank=True, null=True, unique=True)
    description = models.CharField(max_length=200, blank=True, null=True)
    date_modified = models.DateTimeField(auto_now_add=True)

    def is_deletable(self):
        # get all the related object
        for rel in self._meta.get_fields():
            try:
                # check if there is a relationship with at least one related object
                related = rel.related_model.objects.filter(**{rel.field.name: self})
                if related.exists():
                    # if there is return a Tuple of flag = False the related_model object
                    return False, related
            except AttributeError:  # an attribute error for field occurs when checking for AutoField
                pass  # just pass as we dont need to check for AutoField
        return True, None

     class Meta:
        abstract = True

示例

假设我们有三个模型 Organization and Department 和 StaffType 一个组织中可以有这么多部门 并且一个组织有一个特定的 StaffType

class StaffType(ModelIsDeletable):
    pensionable = models.BooleanField(default=False)

class Organization(ModelIsDeletable):
    staff_type = models.ForeignKey(to=StaffType)


class Department(ModelIsDeletable):
    organization = models.ForeignKey(to=Organization, to_field="id")

所以在添加一些信息后说你想删除一个组织模型实例 已经绑定到一个部门

例如我们有 组织表 =>(名称 = 工程,pk = 1) 部门表 => (name=Developer, organization_fk=1, pk=1)

现在,当您尝试使用 pk 获取组织后删除组织时

a_org = Organization.objects.get(pk=1)

有了这个,你可以检查它是否可以删除

deletable, related_obj = a_org.is_deletable()

if not deletable:
    # do some stuff with the related_obj list

else:
    # call the delete function
    a_org.delete()

【问题讨论】:

标签: python django django-models


【解决方案1】:

您的问题似乎是“如果我删除此模型对象,如何检测将删除哪些相关模型对象?”或“如果我删除此行,如何检测将删除哪些相关行?”

另一种选择是使用事务,执行删除,保存 django 提供的信息,但在提交更改之前回滚。这适用于 Postgres 和 MySQL 等数据库,但我不知道其他数据库。

在此示例中,我想知道如果我删除名为“pdemo”的组织会删除什么,并且我看到它有 408 个相关的 Property 对象。

https://gist.github.com/cgthayer/25aa97bb4b74efb75e3467fb7bbdaacb

>>> from django.db import transaction
>>> transaction.set_autocommit(autocommit=False)
>>> o = Organization_v2.objects.get(name='pdemo')
>>> del_info = o.delete()
>>> del_info
(1404, {'data.Property': 408, [..more stuff..], 'data.Organization_v2': 1})
>>> Property.objects.filter(scope__organization_id=o).count()
0
>>> transaction.rollback()
>>> o = Organization_v2.objects.get(name='pdemo')
>>> Property.objects.filter(scope__organization_id=o).count()
408

这可以翻译成通用函数。

在研究这个时,我发现许多旧的解决方案使用 django.contrib.admin 中的函数来确定这一点,但这是一个未记录的 api,似乎不时更改,因此使用事务似乎更容易 iff 你的数据库支持它。

【讨论】:

    猜你喜欢
    • 2013-08-25
    • 1970-01-01
    • 2018-07-19
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 2015-08-11
    • 1970-01-01
    相关资源
    最近更新 更多