如何在django中通过多对一关系中同一相关对象的两个属性进行过滤



我的模型结构如下:

class OneModel(model):
not_important = IntegerField()

class RelatedModel():
propertyA = IntegerField()
propertyB = IntegerField()
original = ForeignKey(OneModel, related_name='related')   

我正在寻找一个原生的django解决方案(没有原始sql),以基本上重新创建这个查询:

select * from OneModel om where not exists
(select id from RelatedModel rm where original_id = om.id and propertyA = 1 and propertyB = 2);

以下是我尝试过的:

OneModel.objects.exclude(related__propertyA=1, related__propertyB=2)

不幸的是,这会选择既不具有与propertyA=1相关的,也不具有与propertyB=2相关的a的OneModel对象,而不是不具有与两个标准都匹配的<strong]单个相关的>的对象。

以下是我的django查询生成的sql:

SELECT lots_of_fields
FROM "OneModel"
WHERE NOT ("OneModel"."id" IN (SELECT U1."original_id" AS Col1
FROM "RelatedModel" U1
WHERE U1."PropertyA" = 1)
AND
"OneModel"."id" IN (SELECT U1."original_id" AS Col1
FROM "RelatedModel" U1
WHERE U1."PropertyB" = 2))

需要明确的是,我的问题不是使用"id" in而不是存在,而是查询的逻辑。

我试着摆弄Q对象,但找不出任何方法来解决这个问题。我也观察了F对象,但它们似乎也不相关。有没有任何方法可以用纯django来表达这一点,或者我有决心写SQL?

至于为什么不使用SQL,我承认这更多的是因为自豪感/想学习新东西,而不是其他任何东西。

这实际上已经在文档中介绍过了——只是有点难找到。

链接如下:向下滚动一点到绿色"注释"部分。

它本质上说,基于外键的排除有点不直观,不能在一个查询中完成。相反,这应该有效(我刚刚将他们的代码移植到你的名字:

query = OneModel.objects.exclude(
related__in=RelatedModel.objects.filter(
propertyA=1,
propertyB=2,
),
)

Django对此进行了优化,这样,尽管看起来有两个查询正在发生,但实际上只对DB进行了一次调用。如果你好奇的话,可以通过query.query来检查它的SQL调用。

最新更新