如何有效清除Django中嵌套的多对多关系?

时间:2019-03-27 22:04:38

标签: django django-models orm

我有一个代码,其中的模型嵌套了许多对许多关系,我需要清除该关系,但是我拥有的解决方案确实很慢,因为它产生了大量的SQL查询。

我拥有的三个模型是Parent,Child,GrandChild。父母可以有很多孩子,孩子可以有很多孙子。 我需要做的是删除给定父母的子女与孙子女的关系。

class Parent:
    children = models.ManyToManyField(Child)

class Child:
    pass

class GrandChild:
    # Can have many parents (aka. the child model) 
    parents = models.ManyToManyField(Child)

parent = models.Parent.objects.get(id=1)
children = parent.children.all()
for child in children:
    children.grandchild_set.clear()

这实际上有效,并且删除了与我们选择的父级关联的子级的子级与子级的所有关联。但是在我的情况下,每个父母通常有超过5,000个孩子,每个孩子大约有2个孙子。但这会使大量的SQL查询并超时。

我想知道是否有任何有效的方法可以批量或通过预取进行此操作。

**注:我只希望清除关系,而不希望删除对象本身。

2 个答案:

答案 0 :(得分:1)

对于M2M关系,您可以浏览可从任何子实例访问的中间表(无关紧要),只需一个查询即可完成该工作:

a_grandchild = GrandChild.objects.filter(child__parent=your_parent_id)[0]
a_grandchild.parents.through.objects.filter(child__parent=your_parent_id).delete()

您还可以通过将Parent s的查询集传递到过滤器来删除多个父级的关系:

parents = Parent.object.filter(...)
GrandChild.objects.filter(child__parent=parents[0])[0] \
    .through.objects.filter(child__parent__in=parents).delete()

答案 1 :(得分:0)

假设您在screen.blit(self.image, self.rect)ForeignKey模型上拥有GrandChild,则可以使用以下方式:

Child

这将使表之间的链连接并向SQL DB发出一个删除命令,而不是每个GrandChild.objects.filter(parent__parent__id=1).delete() 发出一个命令。

编辑:清除关系

如果您想清除child in children的关系,请执行grand_child.parent

update

希望有帮助!