filter tags of django-taggit in Django's Queryset
<p>Having the following models:</p>

<pre><code>class Post(models.Model):
    title = models.CharField(max_length=250)
    tags = TaggableManager()
</code></pre>

<p>and the data areï¼</p>

<pre><code>**post.title**                          **post.tags**
Django By Example                       python,django,web
Who was Django Reinhardt                python,django,
Test-Driven Development with Python     python,web
Python for Data Analysis                python,data         
Learning Python                         python
Programming Python                      python
Automate the Boring Stuff with Python   python
</code></pre>

<p>I try to code below</p>

<pre><code>&gt;&gt;&gt; alist=Post.objects.filter(tags__name__in=["data","python"])
&gt;&gt;&gt; for i in alist.annotate(sam_tags=Count('tags')):
...     print("\n---",i)
...     print("tags of it : ",i.tags.all())
...     print("value of sam_tags : ",i.sam_tags)
... 

--- Django By Example
tags of it :  [&lt;Tag: django&gt;, &lt;Tag: python&gt;, &lt;Tag: web&gt;]
value of sam_tags :  1

--- Who was Django Reinhardt
tags of it :  [&lt;Tag: django&gt;, &lt;Tag: python&gt;]
value of sam_tags :  1

--- Automate the Boring Stuff with Python
tags of it :  [&lt;Tag: python&gt;]
value of sam_tags :  1

--- Test-Driven Development with Python
tags of it :  [&lt;Tag: python&gt;, &lt;Tag: web&gt;]
value of sam_tags :  1

--- Learning Python
tags of it :  [&lt;Tag: python&gt;]
value of sam_tags :  1

--- Python for Data Analysis
tags of it :  [&lt;Tag: data&gt;, &lt;Tag: python&gt;]
value of sam_tags :  2

--- Programming Python
tags of it :  [&lt;Tag: python&gt;]
value of sam_tags :  1
&gt;&gt;&gt; 
</code></pre>

<p>why is the value of slist[0].sam_tags (post:Django By Example) equal to 1?</p>

<p>I think the post object of (post:Django By Example) has three tags [python,django and web] after reading the Django's documentation.</p>

<p><a href="https://docs.djangoproject.com/en/1.10/ref/models/querysets/#count" rel="nofollow">https://docs.djangoproject.com/en/1.10/ref/models/querysets/#count</a></p>

<p>It said that  <strong>Count(expression)</strong> returns the number of objects that are related through the provided expression. 
so the code </p>

<pre><code>&gt;&gt;&gt;alist[0].tags.all() 
[&lt;Tag: django&gt;, &lt;Tag: python&gt;, &lt;Tag: web&gt;]
</code></pre>

<p>shows there are three tags in alist[0].tags,</p>

<pre><code>&gt;&gt;&gt; slist=alist.annotate(sam_tags=Count('tags'))
&gt;&gt;&gt; slist[0].tags.all()
[&lt;Tag: django&gt;, &lt;Tag: python&gt;, &lt;Tag: web&gt;]
&gt;&gt;&gt; slist[0].sam_tags
1
</code></pre>

<p>but here I get the value 1,<br>
why?</p>

<p>I understand that Django is counting only the "python" and "data" tags which I included in my filter clause - other tags are not counted.</p>

<p>The output of "slist[0].tags.all()" shows that slist[0] has three tags related with itself. Because the documentation of django says that Count(expression) returns the number of objects that are related through the provided expression, slist[0].sam_tags should be 3 according to the documentation, but django-taggit make slist[0].sam_tags to be 1. </p>

<p>So what I really want to know is how django-taggit lets Count(expression) in the filter clause only calculate the number of tags in the filter condition .</p>

<p>Django is counting only the <code>python</code> and <code>data</code> tags which you included in your filter clause - other tags are not counted.  (Note that the only example with <code>sam_tags</code> of 2 is the one tagged both <code>data</code> and <code>python</code>.)  This is probably unexpected behavior, but makes sense if you consider how the underlying SQL is executed.  See this example from a similar schema to yours:</p>

<pre><code>&gt;&gt;&gt; a = Article.objects.filter(tags__slug__in=['python']).annotate(num_tags=Count('tags'))[0]
&gt;&gt;&gt; a.num_tags
1
&gt;&gt;&gt; a.tags.count()
2
</code></pre>

<p>If I change the filter clause to filter on somethign other than tags, it behaves as expected:</p>

<pre><code>&gt;&gt;&gt; Article.objects.filter(pk=a.pk).annotate(num_tags=Count('tags'))[0].num_tags
2
&gt;&gt;&gt; Article.objects.filter(pk=a.pk).annotate(num_tags=Count('tags'))[0].tags.count()
2
</code></pre>

python django django-1.9 django-taggit