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 是一个查询集,tagsTag 对象的 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 列表。”

【讨论】:

好的。我会尽快试试这个。顺便说一句,tagsTag 模型都已经分别包含 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 字段查询的主要内容,如果未能解决你的问题,请参考以下文章

Django Queryset __in 列表中没有值

Python-Django 如何将对象列表分配给 M2M?

Unhashable 类型:尝试在 Django 中使用 post_save 动态添加 m2m 关系时出现“列表”错误

使用In-cell下拉列表中的值自动填充单元格 - VBA

我们如何在没有列表理解的情况下在 m2m 字段的 django 管理面板中显示用户

通过 m2m 关系的直通表的值过滤 django 查询集