简体   繁体   English

Django:如何过滤多对多字段的子集?

[英]Django: how to filter on subset of many-to-many field?

Let's say I have the classic Article and Tag models. 假设我有经典的ArticleTag模型。 How can I filter all Article models that have at least both tags A and B . 如何过滤所有至少具有标签AB Article模型。 So an Article with tags A , B , and C should be included but not the article with tags A and D . 因此,应包括带有标签ABC的文章,但不包括带有标签AD的文章。 Thanks! 谢谢!

This question might be old but I have not found any built-in solution in django (like __in filter tag) 这个问题可能很旧,但是我在django中没有找到任何内置解决方案(例如__in filter标签)

So to keep your example. 因此,保持您的榜样。 We have M2M relationship between Article and Tags and want to get all articles which have the given tags, A,B,C. 我们在文章和标签之间具有M2M关系,并希望获得所有具有给定标签A,B,C的文章。 There is no straightforward solution in Django and we have to think back to SQL(do not worry, we still can do everything in Django ORM) In M2M relationship there needs to be a common table which connects the both relations. Django中没有简单的解决方案,我们必须回想起SQL(不用担心,我们仍然可以在Django ORM中完成所有工作)。在M2M关系中,需要有一个将两个关系连接在一起的公用表。 Let's call it TagArticle. 我们称之为TagArticle。 A row in this table is just a tag and an article ids. 该表中的一行只是标签和商品ID。

What we effectively have to do is this: 我们实际上要做的是:

1) Filter the common TagsArticle table to get only the rows with the A,B, or C tags. 1)过滤通用的TagArticle表,以仅获取带有A,B或C标签的行。

2) Group the found rows by the Article and count the rows. 2)按文章对找到的行进行分组,并对行进行计数。

3) Filter out all rows where the count is smaller then the number of tags(3 in our example) 3)筛选出计数小于标签数量的所有行(在我们的示例中为3)

4) Now join or filter the Article table with the previous result 4)现在使用上一个结果联接或过滤Article表

Fortunately, we do not have to access the TagArticle table directly in Django. 幸运的是,我们不必直接在Django中访问TagArticle表。 The pseudo code is then: 伪代码为:

 from django.db.models import Count
 ...
  tags = ['A', 'B', 'C']
  articleQS = Tag.objects.filter(name__in=tags).values('article')
  .annotate(tagCount=Count('article'))
            .filter(catCount=len(tags)).values('article')

        articles = Article.objects.filter(id__in=articleQS)

Let's say Tag is: 假设Tag为:

class Tag(models.model):
   article = models.ForeignKey('Article')
   name = models.CharField(max_length=2)

Then I think you can do: 那我想你可以做到:

a_ids = Tag.objects.filter(name='A').values_list('article_id')
b_ids = Tag.objects.filter(name='B').values_list('article_id')
Article.objects.filter(id__in=a_ids).filter(id__in=b_ids)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM