python - Django 在删除模型之前检查模型是否有相关对象

标签 python django django-models

在寻找一种方法来检查是否可以在 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

示例

假设我们有三个模型组织、部门和员工类型 一个组织中可以有很多部门 一个组织有一个特定的 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")

所以假设添加一些信息后您想要删除组织模型实例 已经与部门绑定(bind)了

例如我们有 组织表=>(名称=工程,PK=1) 部门表=>(名称=开发人员,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()

最佳答案

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

另一个选择是使用事务,执行删除,保存 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,似乎会不时更改,因此使用事务似乎更容易< em>只要你的数据库支持它。

关于python - Django 在删除模型之前检查模型是否有相关对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39727624/

相关文章:

Python 正则表达式,保留字母数字但删除数字

python - 如何在元类中自动生成属性?

Django自定义加载外键

python - Django模型无法调用应用程序模块方法

Django 1.11 - 基于其他表排除的查询

python - 两部分发布请求以获取 CSRF token ,然后发出另一个请求

python - python 调试器如何工作?

django - 向 Django 模板中的变量添加值

python - 如何在 Django 模型上为相关字段生成索引?

python - GeoDjango & SpatiaLite - 过滤附近的物体