Django:使用“in”列表中的每个值进行 M2M 字段查询
Posted
技术标签:
【中文标题】Django:使用“in”列表中的每个值进行 M2M 字段查询【英文标题】:Django: M2M field query using 'in' each value in a list 【发布时间】:2018-09-30 21:48:53 【问题描述】:我正在尝试查找具有 tags
中包含的所有标签的 Problem
对象。
我有以下型号。
class Tag(models.Model):
name = models.CharField(verbose_name='Tag Name', max_length=50)
description = models.CharField(verbose_name='Description', max_length=100, null=True, blank=True)
class Problem(models.Model):
name = models.CharField(verbose_name='Problem Name', max_length=250)
contest_info = models.ManyToManyField(ContestInfo, verbose_name='Contest Info')
tags = models.ManyToManyField(Tag, verbose_name='Tags')
我关注了这些帖子:Post-1 和 Post-2。 但是,没有一个有效。
我的方法。
方法 1
query = [Q(tags__id__in=[tag]) for tag in tags]
problems = problems.filter(reduce(__and__, query))
返回空查询集。
方法 2
for tag in tags:
problems &= problems.filter(tags__id__in=[tag])
返回 OR 的结果而不是 AND。
使用intersection()
也会得到相同的结果。
我想解决列表中包含所有标签的问题。如何做到这一点?
注意:problems
是一个查询集,tags
是 Tag
对象的 ID 列表。
【问题讨论】:
看看***.com/questions/13270513/… 使用postgresql? @Basalex 是的。我用的是postgresql。 @itzMEonTV 谢谢。这帮助并解决了问题。 :D 【参考方案1】:对于 postgresql,您可以这样做(已测试):
from django.contrib.postgres.aggregates import JSONBAgg
problems = Problem.objects.annotate(tags_ids=JSONBAgg('tags__id'))
problems = problems.filter(tags_ids__contains=tags, tags_ids__contained_by=tags)
*其中“tags 是 Tag 对象的 id 列表。”
【讨论】:
好的。我会尽快试试这个。顺便说一句,tags
和 Tag
模型都已经分别包含 unique
id 和对象。那么,我还需要通过DISTINCT
过滤它们吗??
我认为您不必使用 DISTINCT,但我不确定,这就是我将其添加到答案中的原因
它运行不正常。它过滤掉了许多对象。 :( 我在problems
上也应用了其他过滤器,不确定是不是这个原因。
你确定你同时使用了 'contains' 和 'contained_by' 吗?我已经检查了几次,它工作得很好
是的,我做到了。它正在过滤掉一些包含所有tags
的对象。【参考方案2】:
我按照this 的回答解决了这个问题。感谢@itzMEonTV。 但是,它需要循环,如果可能的话,我想在不循环的情况下实现这一点。
这是解决方案。
for tag in tags:
problems = problems.filter(tags__id=tag)
【讨论】:
以上是关于Django:使用“in”列表中的每个值进行 M2M 字段查询的主要内容,如果未能解决你的问题,请参考以下文章
Unhashable 类型:尝试在 Django 中使用 post_save 动态添加 m2m 关系时出现“列表”错误