用另一个QuerySet的查询过滤Django QuerySet:可行吗?

14

假设我创建了一个类似于以下的QuerySet:

q0  = Thing.objects.all()
fq0 = q0.filter(x=y)

在时间t0,我向Thing数据库中添加了一些新的内容。这些内容组成了查询集:

q1 = Thing.objects.filter(created_gt=t0)

我想生成查询集:

fq = (q0 | q1).filter(x=y)

不需要知道 x 或 y 是什么。换句话说,我想能够做这样的事情:

fq1 = q1.filter(query=fq0.query)
fq = fq0 | fq1

这是可能的吗?手动设置

q1.query = fq0.query

仅仅设置了 q1 == fq0。我看到有些人询问如何从一个查询集中提取SQL语句,但这并不能真正帮助我。

3个回答

32

这样的话怎么样:

Thing.objects.filter(field__in=Another_Thing.object.filter())

Django 能够执行查询和子查询。


5
我认为您的意思是Another_model.objects.filter()或者只使用another_queryset - Greg Kaleka

1
多年后,我找到了一个解决方案。
您可以使用查询集的__dict__属性。例如:
o = Model.objects.filter(arg=param)
o2 = Model.objects.all()
o2.query.__dict__ = o.query.__dict__
o2.filter(arg2=param2)

o2现在将通过arg和arg2进行过滤!

我使用这个来将ModelChoiceField的过滤器传递给django-jet自动完成视图(fork at https://github.com/paulorsbrito/django-jet)。

希望这能帮助有困难的人。


1
擅自处理 __*__ 字段绝非明智之举,它们是内部字段。 - Elektordi
1
我不同意。如果它们是内部的,不应该被触碰,那么 Python 应该像 Java 或 C++ 一样设计。这就是 Python! - Paulo Brito
我只是说这是个坏主意,我并没有说你不应该这么做... ;) 在对象上使用那些内部操作的人应该知道它意味着什么。因为团队更改了一些内部操作而导致一些外部代码出现问题,所以有很多著名库的错误报告! - Elektordi

0
据我从查询集和查询模块中了解,Django似乎没有保留查询集中发送的参数的记录。它将所有内容直接转换为低级别的查询片段,然后丢弃给定的标记。因此,如果没有先前知识,想要确定查询集是如何被过滤的是一项相当复杂的任务。
您可以通过手动创造以下类似的东西来完成此任务:
q0 = Thing.objects.all()
filter_kwargs = {'x': y}
fq0 = q0.filter(**filter_kwargs)
fq0.saved_filter_kwargs = filter_kwargs

##### snip #####

fq1 = q1.filter(**fq0.saved_kwargs)

这有点棘手。最好尝试以不同的方式解决这个问题。我建议您发布另一个问题,并在其中包括您在整体上想要实现什么,我们可能能够帮助您提出更好的架构。


大局:通过仅过滤q1生成fq,将缓存fq0。你说得对,这是一个不好的解决方案。当你缓存东西时,它变得更加恶劣。幸运的是,我找到了更好的解决方案。感谢你的帮助。虽然我需要更多的声望,所以无法给你点赞。 - dmr parthenon
@dmrparthenon,你应该回答自己的问题并分享你找到的解决方案,以帮助社区,并将其标记为已解决的答案。 - Shil Nevado

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接