添加标签功能
在实现你的评论系统之后,你需要创建一个方法去标注你的博客(就是贴标签)。你可以通过整合第三方Django 标签 应用程序到你的项目中去 做这些。django-taggit
是一个可复用的 应用程序,主要为你提供 Tag
模型,以及一个很简单的在任何模型中添加标签的管理器。 你可以在这个链接看到它的源代码;
首先你需要pip
允许下面的代码去安装 django-taggit
pip install django_taggit==1.2.0
这是,打开mysite
项目的settings.py
文件,并且在 INSTALLED_APPS
设置中添加 taggit
, 如下:
打开你 blog
应用程序的 models.py
文件,并且在Post
模型中添加一个 通过 django-taggit
提供的 TaggableManager
管理器,使用下面的代码:
from taggit.managers import TaggableManager
class Post(models.Model):
# ....
tags = TaggableManager()
这个 tags
管理器将允许你 从 Post
对象中添加,检索,删除标签。
允许下面的命令为你模型的更改创建一个迁移:
python manage.py makemigrations blog
你将得到下面的输出:
image.png
现在,运行下面的命令为 django-taggit
模型去创建数据库必须的表,并且同步你模型的更改。
python manage.py migrate
你将看到一些输出,表明这个迁移已经被应用了,如下:
image.png
你的数据库现在准备去使用 django-taggit
模型了。
让我们去探索如何去使用 tags
管理器。通过 python manage.py shell
命令打开终端,并且输入下面的代码。首先将将检索到你的一个帖子。(这个 帖子的ID = 1):
>>> from blog.models import Post
>>> post = Post.objects.get(id=1)
这时,去给它添加一些标签,并且检索这些标签,检查它们是否被成功添加:
>>> post.tags.add('music', 'jazz', 'django')
>>> post.tags.all()
<QuerySet [<Tag: django>, <Tag: music>, <Tag: jazz>]>
最后,移除一个标签,并且再次检查这个标签列表:
>>> post.tags.remove('django')
>>> post.tags.all()
<QuerySet [<Tag: music>, <Tag: jazz>]>
比较简单,对吧?运行 python manage.py runserver
命令再次去打开开发者服务器,并且在你的浏览器中打开 http://127.0.0.1:8000/admin/taggit/tag/
你将看到taggit
应用程序的带有Tag
对象列表的管理员页面。
导航到 http://127.0.0.1:8000/admin/blog/post/, 点击一个帖子去编辑他。 你将看到现在的帖子包含一个 性的 Tags 字段,如下,这里可以很简单的编辑标签:
现在,你需要去编辑你的 博客帖子去显示标签。打开 blog/post/list.html
模板,并且去添加下面的 HTML 代码,在 帖子 标题之后。
<p class="tags">Tags: {{ post.tags.all|join:", " }}</p>
这个 join
摹本过滤器工作和 Python 字符串的 join()
方法工作相似,用给定的字符串连接元素。在浏览器中打开 http://127.0.0.1:8000/blog/。 你应该能在每一个 帖子 标题下面看到标签列表。
下一步,你将编辑 post_list
视图去让用户列出所有指定标签的帖子。打开你 blog
应用程序的 views.py
文件。从django-taggit
中导入 Tag
模型,并且修改 post_list
使用一个可选的标签过滤帖子。如下:
from taggit.models import Tag
def post_list(request, tag_slug=None):
object_list = Post.published.all()
tag = None
if tag_slug:
tag = get_object_or_404(Tag, slug=tag_slug)
object_list = object_list.filter(tags__in=[tag])
paginator = Paginator(object_list, 3) # 每 3 篇博客一页
# .....
post_list
视图现在工作如下:
- 它提供了一个
tag_slug
可选参数,它有一个None
默认值。这个参数将在 URL 中传递。 - 在视图内部,您构建初始的查询集,检索所有已发布的帖子,如果这里提供了 标签 slug。你可以用 slug 使用
get_object_or_404()
快捷方式得到Tag
对象。 - 然后,通过包含给定标记的文章来筛选文章列表,因为这是一个 多对多的关系,您必须根据给定列表中包含的标记筛选帖子,在这个例子中,该元素只包含一个元素。使用
__in
字段进行查找。多对多关系发生在一个模型的多个对象和另一个模型的多个对象之间的联系。在你的应用程序中,一个帖子可以有多个标签并且一个标签可以关联多个帖子。你可以学习更多创建多对多关系。在第五章:在你的网站中分享内容。你也可以在这个链接中发现更多有关的知识。
请记住,查询集是惰性的。只有在呈现模板时对 post 列表进行循环时,才会计算用于检索 post 的查询集。
最后,在视图的底部修改 render()
函数,通过 tag
变量渲染到模板中, 这个视图看起来像这个样子:
def post_list(request, tag_slug=None):
object_list = Post.published.all()
tag = None
if tag_slug:
tag = get_object_or_404(Tag, slug=tag_slug)
object_list = object_list.filter(tags__in=[tag])
paginator = Paginator(object_list, 3) # 每 3 篇博客一页
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
# 如果页面不是整数,就返回第一页
posts = paginator.page(1)
except EmptyPage:
# 如果页面超出范围,就提交结果的最后一页
posts = paginator.page(paginator.num_pages)
return render(request,
'blog/post/list.html',
{'posts': posts,
'tag': tag,
'page': page})
打开你 blog
应用程序的 urls.py
文件,注释掉基于类的 PoslListView
url 模式。取消掉 post_list
视图,如下:
path('', views.post_list, name='post_list'),
# path('', views.PostListView.as_view(), name='post_list'),
添加以下附加的URL模式来按标记列出文章:
path('tag/<slug:tag_slug>/',
views.post_list, name='post_list_by_tag'),
正如你所见的,两个模式都指向了相同的视图,但是你使用名称区分它们。第一个模式调用 post_list
视图 时没有任何可选参数。第二个模式调用 post_list
视图的时候使用了 tag_slug
参数。你使用一个 slug
路径转换器 将 参数匹配为 带有 ASCII 字母或数字的小写字符串,加上连字符和下划线字符。
自从你使用了 post_list
视图,编辑 blog/post/list.html
模板,并且去使用 posts
对象 修改 分页器:
{% include "pagination.html" with page=posts %}
在 {% for %}
循环之上添加下面这些行:
{% if tag %}
<h2> Posts tagged with "{{ tag.name }}" </h2>
{% endif %}
如果一个用户访问这个 博客,它将看到一个所有帖子的列表。如果他们通过贴有特殊标签的过滤帖子,他们将看到他们正在过滤的标签。
现在,改变标签的显示方式,如下:
<p class="tags">
Tags:
{% for tag in post.tags.all %}
<a href="{% url "blog:post_list_by_tag" tag.slug %}">
{{ tag.name }}
</a>
{% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
在上面的代码中,循环一个 post 的所有标记,显示一个到 URL 的自定义链接,以通过该标记筛选 post。你使用 {% url "blog:post_list_by_tag" tag.slug %}
,使用URL名称和slug标记作为其参数。用逗号分隔标签。
在你的浏览器中打开 http://127.0.0.1:8000/blog/,并且点击任何一个 tag 链接。您将看到使用该标记的文章列表,如下:
网友评论