Django 删除未使用的父模型
我有这两种型号:Django 删除未使用的父模型,django,Django,我有这两种型号: Parent(models.Model): name=models.CharField(max_length=10) Child(models.Model): parent=models.ForeignKey(Parent) name=models.CharField(max_length=10) 我正在寻找一种有效的方法来消除没有孩子的父母的痛苦。目前,我正在使用原始SQL执行此操作: from django.db import connection
Parent(models.Model):
name=models.CharField(max_length=10)
Child(models.Model):
parent=models.ForeignKey(Parent)
name=models.CharField(max_length=10)
我正在寻找一种有效的方法来消除没有孩子的父母的痛苦。目前,我正在使用原始SQL执行此操作:
from django.db import connection
SQL="DELETE FROM app_parent WHERE app_parent.id NOT IN (SELECT id FROM app_child"
它正在运行两个查询,我仍然希望使用Django ORM。同样,使用ORM,我首先要获得子项列表,然后检查父项id是否存在
有没有更快的方法呢?使用左外连接
您可以通过使用相关名称筛选(..)
来检测没有子项的父项
,并检查该关系\u是否为空
因此,我们可以通过以下方式获得一个无子项的父项列表:
Parent.objects.filter(child__isnull=True).distinct()
然后,我们可以.delete()
那些父项
s:
Parent.objects.filter(child__isnull=True).distinct().delete()
因此,在这里,我们用以下事实来注释每个父项
,父项
的主键
是否存在子项
。然后,我们过滤(..)
这个注释应该是False
这将导致如下查询:
SELECT `parent`.*
FROM `parent`
WHERE NOT EXISTS (
SELECT `child`.`id`
FROM `child`
WHERE `child`.`parent_id` = `parent`.`id`
) = True
受保护的父对象(到其他关系)
但是请注意,如果通过其他
外键
仍引用父项,则此操作可能会失败。例如,如果不仅有一个孩子,还有一个叔叔
关系,它指向一个家长
,那么.delete()
可能会失败,因为仍然有叔叔
引用一个或多个家长
而没有孩子。这实际上仍然是一个查询,但它有子查询。然而,它将以相同的时间复杂度运行。我们可以再加快一点。再加快一点@willemvanonsem谢@willem Van Onsem。稍微检查一下其他可能的相关型号,它就完美无缺了,速度也提高了一点。@NieSelam:第二个attemt(使用存在)怎么样。你能提供时间吗。也许这对未来的读者来说是件好事。好吧,让我试试并粘贴我的结果。
from django.db.models import Exists, OuterRef
Parent.objects.annotate(
has_children=Exists(
Child.objects.filter(parent=OuterRef('pk').values('id'))
)
).where(has_children=False).delete()
SELECT `parent`.*
FROM `parent`
WHERE NOT EXISTS (
SELECT `child`.`id`
FROM `child`
WHERE `child`.`parent_id` = `parent`.`id`
) = True