把queryset作为参数传递给django中的__in?

ezykj2lf  于 2022-12-01  发布在  Go
关注(0)|答案(2)|浏览(144)

我有一个对象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(),所以我不认为有任何简单的方法可以解决这个问题)。
如何将未计算的queryset作为参数传递给__in查找?
我想这样做:

ids_to_delete = self.items.all().values("id")
other_object.items.filter(item_id__in=ids_to_delete).delete()
u5rb5r59

u5rb5r591#

您可以将QuerySet传递给查询:

other_object.items.filter(id__in=self.items.all()).delete()

这将把它转换成一个子查询。但不是所有的数据库,特别是MySQL数据库,都能很好地处理这样的子查询。此外,Django * 手动 * 处理.delete()。它将因此进行一个查询来获取条目的主键,然后触发删除逻辑因此.delete()不是作为一个查询完成的,而是作为至少两个查询完成的,并且由于X1 M5 N1 X触发器的X1 M4 N1 X而通常具有更大的量。
但是请注意,您在这里 * 移除 * Item对象,而不是从other_object中“取消链接”。为此,可以使用**.remove(…)**[Django-doc]。

neskvpey

neskvpey2#

我应该尝试一下我发布的代码示例,实际上你可以做到这一点。文档中给出了一个示例,但它说“小心使用嵌套查询并了解数据库服务器的性能特征”,并建议不要这样做,将子查询转换为列表:

values = Blog.objects.filter(
        name__contains='Cheddar').values_list('pk', flat=True)
entries = Entry.objects.filter(blog__in=list(values))

相关问题