检索相似帖子
现在你已经为博客 帖子 实现了标签,你可以通过标签做许多有趣的事情。标签允许你以非分层的方式分类帖子。类似主题的帖子会有几个相同的标签。你将创建一个功能,通过共享标签的数量显示帖子。使用这个方法,在用户阅读帖子的时候,你可以建议它们去读一读其他相关的帖子。
为了从一个特定的帖子检索相似的帖子,你需要完成下面步骤:
- 从当前的帖子中检索到所有的标签。
- 从这些标签中得到所有的帖子。
- 将当前的帖子从帖子列表中剔除,以免出现重复推荐。
- 通过和当前帖子共享的标签数量排序这些帖子。
- 如果有两个或两个以上的帖子的标签数量相同,就推荐最近的帖子。(译者注:这个“最近”,是指发布时间。也就是先按相同帖子数量排序,然后再按发布时间排序。)
- 将查询限制为想要推荐的数量。
这些步骤将翻译成一个复杂的查询集,它将被包含在你的 post_detail
视图中。在你的 blog
应用程序的 views.py
加新的一行,并且在顶端添加下面这行:
from django.db.models import Count
这是 Django ORM 的 Count
聚合函数,此函数允许您执行标记的聚合计数。django.db.models
包含下面这些聚合函数:
-
Avg
: 平均数 -
Max
:最大数 -
Min
: 最小数 -
Count
:对象的总数
你可以在这个链接中学习到更多有关聚合的知识.
在 post_detail
视图里面的 render()
函数之前添加下面这些行,具有相同的缩进水平:
post_tags_ids = post.tags.values_list('id', flat=True)
similar_posts = Post.published.filter(tags__in=post_tags_ids).exclude(id=post.id)
similar_posts = similar_posts.annotate(same_tags=Count('tags')).order_by('-same_tags', '-publish')[:4]
上述代码如下:
- 检索当前文章 标签的 的 ID 的Python列表。
values_list()
查询集为给定字段返回带有值的元组。你通过flat=True
去得到一个值例如 [1, 2, 3, ....] 而不是一个 例如 [(1, ), (2, ), (3, )...] 的单元组列表。 - 您将获得包含任何这些标签的所有帖子,不包括当前帖子它自己。
- 你使用
Count
聚合函数去生成一个 可计算字段same_tags
,包含与所有查询的标签共享的标签的数量。 - 你通过共享标签数量排序结果(递减序), 并且通过
publish
去显示最近的帖子,首先是根据共享的标签数量。对结果进行前片,仅仅只要前四个。
添加 similar_posts
对象到 render()
功能的上下文字典中,如下:
return render(request,
'blog/post/detail.html',
{'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form,
'similar_posts': similar_posts})
现在,编辑 blog/post/detail.html
模板,并且在 帖子评论列表添加下面的代码:
<h2>Similar posts</h2>
{% for post in similar_posts %}
<p>
<a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
</p>
{% empty %}
There are no similar posts yet.
{% endfor %}
这个帖子详情页面看起来如下所示:
Snipaste_2020-08-03_14-13-32.jpg您现在可以成功地向您的用户推荐类似的文章。 django-taggit
也包含了一个 similar_objects()
管理器,你可以使用它通过共享标签检索对象,你能在 django-taggit 得到更多管理器知识。
你也可以在 帖子 详情模板中添加 标签列表,就像你在 blog/post/list.html
模板中添加一样。
网友评论