给定我有一个Product
模型和一对多ProductTag
模型。
class Product(models.Model):
[...]
class ProductTag(models.Model):
product = models.ForeignKey(Product)
tag_value = models.CharField()
[...]
如果我有3个带有一些标签的产品:
- 产品A[TagA]
- 产品B[TagB]
- 产品C[TagB/TagC]
我想动态查询";产品";带有一些标签
- 此查询只返回";产品A";(如预期(
Product.objects.filter(Q(producttag__tag_value="TagA"))
- 此查询返回所有3个产品(如预期(
Product.objects.filter(
Q(producttag__tag_value="TagA") | Q(producttag__tag_value="TagB")
)
- 我希望下面的查询只返回"产品C">
Product.objects.filter(
Q(producttag__tag_value="TagB") & Q(producttag__tag_value="TagC")
)
但是我得到一个空的查询集。为什么查询#3不起作用?
使用__in
查询也会返回错误的结果(如预期(
Product.objects.filter(producttag__tag_value__in=["TagB", "TagC"])
上面的查询同时返回ProductB/ProductC。
更新
我使用Q对象进行查找的原因是,查询基于来自API端点的用户输入。例如
- "tag=TagA">
- "tag=TagA AND tag=TagB">
- "tag=TagA AND NOT tag=TagC">
所以我需要根据用户输入运行动态Django查询,而不能对某些查询进行硬编码。
以下查询工作:
qs1 = Product.objects.filter(Q(producttag__tag_value="TagB"))
qs2 = Product.objects.filter(Q(producttag__tag_value="TagC"))
queryset = qs1 & qs2
上面的查询只返回ProductC。
大致基于这个答案https://stackoverflow.com/a/33271387/1682844
查询#3有效地要求ProductTag.tag_value
在单行上同时等于TagB
和TagC
,这显然是不可能的。这是SQL查询语法/模型的结果,您总是基于表的单行进行筛选。
我没有想到比链接EXISTS
子句(仅适用于Django 3.x(更花哨、更具性能的东西:
rel_tag = ProductTag.objects.filter(product=OuterRef('pk'))
Product.objects.filter(
Exists(rel_tag.filter(tag_value="TagB")) &
Exists(rel_tag.filter(tag_value="TagC"))
)