拥有以下型号:
class Post(models.Model):
title = models.CharField(max_length=250)
tags = TaggableManager()
,数据是:
**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
我尝试在下面编码
>>> alist=Post.objects.filter(tags__name__in=["data","python"])
>>> 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 : [<Tag: django>, <Tag: python>, <Tag: web>]
value of sam_tags : 1
--- Who was Django Reinhardt
tags of it : [<Tag: django>, <Tag: python>]
value of sam_tags : 1
--- Automate the Boring Stuff with Python
tags of it : [<Tag: python>]
value of sam_tags : 1
--- Test-Driven Development with Python
tags of it : [<Tag: python>, <Tag: web>]
value of sam_tags : 1
--- Learning Python
tags of it : [<Tag: python>]
value of sam_tags : 1
--- Python for Data Analysis
tags of it : [<Tag: data>, <Tag: python>]
value of sam_tags : 2
--- Programming Python
tags of it : [<Tag: python>]
value of sam_tags : 1
>>>
为什么slist [0] .sam_tags(post:Django By Example)的值等于1?
在阅读Django的文档之后,我认为(post:Django By Example)的post对象有三个标签[python,django和web]。
https://docs.djangoproject.com/en/1.10/ref/models/querysets/#count
它表示 Count(表达式)返回通过提供的表达式相关的对象数。 所以代码
>>>alist[0].tags.all()
[<Tag: django>, <Tag: python>, <Tag: web>]
显示alist [0] .tags中有三个标签,
>>> slist=alist.annotate(sam_tags=Count('tags'))
>>> slist[0].tags.all()
[<Tag: django>, <Tag: python>, <Tag: web>]
>>> slist[0].sam_tags
1
但是我得到的值是1,
为什么呢?
我知道Django只计算&#34; python&#34;和&#34;数据&#34;我包含在我的过滤条款中的标签 - 其他标签不计算在内。
&#34; slist [0] .tags.all()&#34;的输出表明slist [0]有三个与自身相关的标签。因为django的文档说Count(表达式)返回通过提供的表达式相关的对象的数量,slist [0] .sam_tags应该是3根据文档,但是django-taggit make slist [0] .sam_tags to是1.
所以我真正想知道的是django-taggit如何让filter子句中的Count(表达式)只计算过滤条件中的标签数。
答案 0 :(得分:1)
Django只计算您在过滤器子句中包含的python
和data
标记 - 其他标记不计算在内。 (请注意,sam_tags
为2的唯一示例是标记为data
和python
的示例。)这可能是意外行为,但如果考虑如何执行基础SQL则有意义。从与您类似的架构中查看此示例:
>>> a = Article.objects.filter(tags__slug__in=['python']).annotate(num_tags=Count('tags'))[0]
>>> a.num_tags
1
>>> a.tags.count()
2
如果我更改filter子句以过滤除标签以外的某些标签,则其行为符合预期:
>>> Article.objects.filter(pk=a.pk).annotate(num_tags=Count('tags'))[0].num_tags
2
>>> Article.objects.filter(pk=a.pk).annotate(num_tags=Count('tags'))[0].tags.count()
2
答案 1 :(得分:1)
通过print(similar_post.query)查询查询是相对直接的 我们可以看到代码只计算了显示该帖子标签的tag_id。
选择“ blog_post”。“ id”,“ blog_post”。“ title”,“ blog_post”。“ slug”,“ blog_post”。“ author_id”,“ blog_post”。“ body”,“ blog_post”。“发布”, “ blog_post”。“创建”,“ blog_post”。“更新”,“ blog_post”。“状态”,COUNT(“ taggit_taggeditem”。“ tag_id”)AS“ same_tags”来自“ blog_post”
INNER JOIN“ taggit_taggeditem” ON(“ blog_post”。“ id” =“ taggit_taggeditem”。“ object_id” AND(“ taggit_taggeditem”。“ content_type_id” = 7))
在哪里(“ blog_post”。“状态” =已发布
AND "taggit_taggeditem"."tag_id" IN (SELECT DISTINCT U0."id" FROM "taggit_tag"
U0 INNER JOIN "taggit_taggeditem" U1 ON (U0."id" = U1."tag_id")
INNER JOIN "django_content_type" U2 ON (U1."content_type_id" = U2."id")
WHERE (U2."app_label" = blog AND U2."model" = post AND U1."object_id" = 8))
AND NOT ("blog_post"."id" = 8))
GROUP BY“ blog_post”。“ id”,“ blog_post”。“ title”,“ blog_post”。“ slug”,“ blog_post”。“ author_id”,“ blog_post”。“ body”,“ blog_post”。“ publish“,” blog_post“。”创建“,” blog_post“。”更新“,” blog_post“。”状态“
ORDER BY“ same_tags” DESC,“ blog_post”。“发布” DESC LIMIT 4