我有一个从模型方法中的查询中获得的对象ID列表,然后我使用该列表从不同的模型中删除对象:
class SomeObject(models.Model):
# [...]
def do_stuff(self, some_param):
# [...]
ids_to_delete = {item.id for item in self.items.all()}
other_object = OtherObject.objects.get_or_create(some_param=some_param)
other_object.items.filter(item_id__in=ids_to_delete).delete()
我不喜欢的是,这需要2个查询(从技术上讲,get_or_create()
需要3个查询,但在实际代码中,它实际上是.filter(some_param=some_param).first()
,而不是.get()
,所以我认为没有任何简单的方法可以解决这个问题(。
如何将未求值的查询集作为参数传递给__in
查找?
我想做一些类似的事情:
ids_to_delete = self.items.all().values("id")
other_object.items.filter(item_id__in=ids_to_delete).delete()
您可以将QuerySet
传递给查询:
other_object.items.filter(id__in=self.items.all()).delete()
这将在子查询中转换它。但并不是所有的数据库,尤其是MySQL数据库,都能很好地处理这样的子查询。此外,Django手动处理.delete()
。因此,它将进行查询以获取项的主键,然后触发删除逻辑(并删除具有CASCADE
依赖关系的项(。因此,.delete()
不是作为一个查询来完成的,而是至少两个查询,并且由于ForeignKey
带有on_delete
触发器,因此数量通常更大。
然而,请注意,您在这里删除Item
对象,而不是";取消链接";这来自CCD_ 12。为此,可以使用.remove(…)
[Django-doc]。
我应该试试我发布的代码示例,事实上你可以做到。文档中给出了一个例子,但它说";要谨慎使用嵌套查询,并了解数据库服务器的性能特征;并建议不要这样做,将子查询强制转换为一个列表:
values = Blog.objects.filter(
name__contains='Cheddar').values_list('pk', flat=True)
entries = Entry.objects.filter(blog__in=list(values))