简体   繁体   English

在Django的Queryset中过滤django-taggit的标签

[英]filter tags of django-taggit in Django's Queryset

Having the following models: 具有以下模型:

class Post(models.Model):
    title = models.CharField(max_length=250)
    tags = TaggableManager()

and the data are: 数据为:

**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

I try to code below 我尝试在下面编码

>>> 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
>>> 

why is the value of slist[0].sam_tags (post:Django By Example) equal to 1? 为什么slist [0] .sam_tags(以Django为例)的值等于1?

I think the post object of (post:Django By Example) has three tags [python,django and web] after reading the Django's documentation. 我认为(post:Django By Example)的post对象在阅读Django文档后具有三个标签[python,django和web]。

https://docs.djangoproject.com/en/1.10/ref/models/querysets/#count https://docs.djangoproject.com/zh/1.10/ref/models/querysets/#count

It said that Count(expression) returns the number of objects that are related through the provided expression. 它说Count(expression)返回通过提供的表达式相关的对象数。 so the code 所以代码

>>>alist[0].tags.all() 
[<Tag: django>, <Tag: python>, <Tag: web>]

shows there are three tags in alist[0].tags, 显示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

but here I get the value 1, 但在这里我得到的值是1
why? 为什么?

I understand that Django is counting only the "python" and "data" tags which I included in my filter clause - other tags are not counted. 我了解Django仅对我包含在我的filter子句中的“ python”和“ data”标签进行计数-其他标签不计算在内。

The output of "slist[0].tags.all()" shows that slist[0] has three tags related with itself. “ slist [0] .tags.all()”的输出显示slist [0]具有与其自身相关的三个标签。 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. 因为django的文档说Count(expression)返回通过提供的表达式关联的对象数,所以根据文档,slist [0] .sam_tags应该为3,但是django-taggit将slist [0] .sam_tags设置为是1。

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 . 所以我真正想知道的是django-taggit如何让filter子句中的Count(expression)仅计算过滤条件中的标签数。

Django is counting only the python and data tags which you included in your filter clause - other tags are not counted. Django只计算您包含在filter子句中的pythondata标记-其他标记不计算在内。 (Note that the only example with sam_tags of 2 is the one tagged both data and python .) This is probably unexpected behavior, but makes sense if you consider how the underlying SQL is executed. (请注意,只有sam_tags为2的示例是同时标记了datapython示例。)这可能是意外的行为,但是如果考虑如何执行基础SQL,这是有道理的。 See this example from a similar schema to yours: 从与您的模式相似的模式中查看此示例:

>>> a = Article.objects.filter(tags__slug__in=['python']).annotate(num_tags=Count('tags'))[0]
>>> a.num_tags
1
>>> a.tags.count()
2

If I change the filter clause to filter on somethign other than tags, it behaves as expected: 如果我更改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

it's relatively straight forward to look into the query by print(similar_post.query) we can see the code only counts the tag_id which belongs to the tags of the post is being shown. 通过print(similar_post.query)来查询查询是相对直接的,我们可以看到代码只对属于帖子标签的tag_id进行计数。

SELECT "blog_post"."id", "blog_post"."title", "blog_post"."slug", "blog_post"."author_id", "blog_post"."body", "blog_post"."publish", "blog_post"."created", "blog_post"."updated", "blog_post"."status", COUNT("taggit_taggeditem"."tag_id") AS "same_tags" FROM "blog_post" SELECT“ 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)) 内联接“ taggit_taggeditem” ON(“ blog_post”。“ id” =“ taggit_taggeditem”。“ object_id” AND(“ taggit_taggeditem”。“ content_type_id” = 7))

WHERE ("blog_post"."status" = published 在哪里(“ 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"."created", "blog_post"."updated", "blog_post"."status" GROUP BY“ blog_post”。“ id”,“ blog_post”。“ title”,“ blog_post”。“ slug”,“ blog_post”。“ author_id”,“ blog_post”。“ body”,“ blog_post”。“发布”, “ blog_post”。“创建”,“ blog_post”。“更新”,“ blog_post”。“状态”

ORDER BY "same_tags" DESC, "blog_post"."publish" DESC LIMIT 4 ORDER BY“ same_tags” DESC,“ blog_post”。“发布” DESC LIMIT 4

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

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