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