Django通过多对多ORM对象中的多个标签进行过滤

Posted

技术标签:

【中文标题】Django通过多对多ORM对象中的多个标签进行过滤【英文标题】:Django filtering by multiple tags in many to many ORM object 【发布时间】:2016-09-05 21:16:06 【问题描述】:

我有三个模型。 QueryQueryStringTagTag。这些模型是我构建的标签云的一部分。一个Query 可以有很多Tags,而Tag 可以有很多Querys。 TagQuery 模型具有连接QueryStringTag 模型的外键,该模型包含有关查询如何与标签关联的所有信息,反之亦然。

这是我的模型...

class Tag(models.Model):
    name = models.CharField(max_length=101)
    use_count = models.IntegerField(default=1)

class QueryStringTag(models.Model):
    tag = models.ForeignKey(Tag, related_name='qstag')
    querystring = models.ForeignKey(QueryString, related_name='qsquerystring')

class QueryString(BaseObject): 
    """
    Query string holds an SQL statement and query properties for execution
    """

    server_id = models.IntegerField()
    schema = models.CharField(max_length=255, blank=True)
    archived = models.BooleanField(default=False)
    query = models.CharField(max_length=60000) 
    variables = models.TextField(blank=True)
    created_by = models.ForeignKey(User, related_name='queries_created')
    updated_by = models.ForeignKey(User, related_name='queries_last_edited')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField()
    touched_by = models.CharField(max_length=1000)
    config = models.TextField(blank=True)
    runs_started = models.IntegerField(default=0)
    runs_completed = models.IntegerField(default=0)
    runs_completed_duration = models.IntegerField(default=0) # total number of seconds spent running this query to completion
    formats = "pretty_html html json prettyjson csv excel tableau".split()

我目前已经设置好了,所以用户点击标签云中任意数量的标签,标签主键数组就会发送到我的 django 视图,看起来像这样:['12', '14', '15']

我需要使用 Django ORM 来检索与用户单击的所有标签相关联的所有查询。因此,如果用户点击标签“用户”、“游戏”和“卡车”,它应该只带回与用户点击的所有标签相关联的查询。这是AND 关系,而不是OR 关系。意思是“Query1”将与“12”、“14”和“15”相关联。

正确的语法是什么?

【问题讨论】:

如果您在QuerySting 中有Tag 作为ManyToManyField,那么实现这一点会更容易。拥有QueryStringTag 的目的是什么? @ShangWang 总而言之,我们的本地开发环境不会接受ManyToManyField。我不得不这样做。 我只用ManyToManyField 完成了这个,并且有很多与此相关的答案:***.com/questions/13270513/… 和***.com/questions/8618068/…。也许原始 sql 会有所帮助。 @ShangWang 这是ManyToManyField,接受它只是拼写出来的。 ManyToManyField 所做的只是制作一个中心连接表,就像我正在做的那样。 我当然知道。也许我遗漏了一些东西,但我的观点是你的设计使得使用 django ORM api 很难做到这一点。虽然我还是不太明白是什么阻碍了你使用ManyToManyField 【参考方案1】:
qsts_pks = QueryStringTag.objects.filter(tag__pk__in=['12', '14', '15']).values_list('id', flat=True)
queries = QueryString.objects.filter(qsquerystring__pk__in=qsts_pks)

相关文档here 和here

【讨论】:

以上是关于Django通过多对多ORM对象中的多个标签进行过滤的主要内容,如果未能解决你的问题,请参考以下文章

ORM操作

如何通过多对多关系获取 django 模型?

django ORM中的RelatedManager(关联管理器)

如何使通过多对多关系连接的模型在 Django admin 中同时在两个地方可编辑?

Django ORM 处理多个多对多关系的方式

Django ORM:构造查询,该查询将在多对多字段的最后位置的对象中的字段上查找匹配项