Django搭建个人博客:文章标签功能

栏目: Python · 发布时间: 6年前

内容简介:“标签”是作者从文章中提取的好在标签功能也有优秀的三方库:首先在

“标签”是作者从文章中提取的 核心词汇 ,其他用户可以通过标签快速了解文章的关注点。每一篇文章的标签可能都不一样,并且还可能拥有多个标签,这是与栏目功能不同的。

好在标签功能也有优秀的三方库: Django-taggit ,省得自己动手设计了。快速开发就是这样,能“借用”就不要自己重复劳动。

安装及设置

首先在 虚拟环境 中安装Django-taggit:

pip install django-taggit

安装成功后,修改项目设置以添加库:

my_blog/settings.py

...
INSTALLED_APPS = [
    ...
    'taggit',
]
...

修改文章模型

标签是文章Model的属性,因此需要修改文章模型。

需要注意的是标签引用的不是内置字段,而是库中的 TaggableManager ,它是处理多对多关系的管理器:

article/models.py

...

# Django-taggit
from taggit.managers import TaggableManager

...
class ArticlePost(models.Model):
    ...

    # 文章标签
    tags = TaggableManager(blank=True)

    ...

然后记得 数据迁移

带标签文章的发表

修改文章的表单类,让其能够提交标签字段:

article/forms.py

...
class ArticlePostForm(forms.ModelForm):
    class Meta:
        ...
        fields = ('title', 'body', 'tags')

然后修改发表文章的视图,保存POST中的标签:

article/views.py

...
def article_create(request):
    # 已有代码
    if request.method == "POST":
        article_post_form = ArticlePostForm(data=request.POST)
        if article_post_form.is_valid():
            new_article = article_post_form.save(commit=False)
            ...
            new_article.save()
            
            # 新增代码,保存 tags 的多对多关系
            article_post_form.save_m2m()
            
            ...

需要注意的是,如果提交的表单使用了 commit=False 选项,则必须调用 save_m2m() 才能正确的保存标签,就像普通的多对多关系一样。

最后就是在发表文章的模板中添加标签的表单项了:

templates/article/create.html

...
<!-- 提交文章的表单 -->
<form method="post" action=".">
    ...
    
    <!-- 文章标签 -->
    <div class="form-group">
        <label for="tags">标签</label>
        <input type="text" 
               class="form-control col-3" 
               id="tags" 
               name="tags"
        >
    </div>
    
    ...
</form>
...

运行服务器,就可以在发表页面看到效果了:

Django搭建个人博客:文章标签功能

多个标签最好用 英文逗号 进行分隔。 中文逗号 有的版本会报错,干脆就不要去使用了。

列表中显示标签

虽然保存标签的功能已经实现了,还得把它显示出来才行。

显示标签最常用的位置是在 文章列表 中,方便用户筛选感兴趣的文章。

修改文章列表的模板,将标签显示出来:

templates/article/list.html

...
<!-- 栏目 -->
...

<!-- 标签 -->
<span>
    {% for tag in article.tags.all %}
        <a href="#"
           class="badge badge-secondary" 
        >
            {{ tag }}
        </a>
    {% endfor %}
</span>

...

链接中的 class 中是Bootstrap定义的 徽章样式

插入位置紧靠在栏目按钮的后面。当然你想放到其他位置也是完全可以的。

刷新列表页面看看效果:

Django搭建个人博客:文章标签功能

标签过滤

有时候用户想搜索带有某一个标签的所有文章,现在就来做这个功能。

与搜索功能一样,只需要调取数据时用 filter() 方法过滤结果就可以了。

修改 <a> 标签中的 href ,使其带有 tag 参数返回到View中:

templates/article/list.html

...

<!-- 标签 -->
<span>
    {% for tag in article.tags.all %}
        <a href="{% url 'article:article_list' %}?tag={{ tag }}"
           class="badge badge-secondary" 
        >
            {{ tag }}
        </a>
    {% endfor %}
</span>

...

然后在View中取得 tag 的值,并进行搜索。

下面的代码将 article_list() 函数完整写出来了(包括上一章末尾没讲的栏目查询),方便读者比对。

article/views.py

...
def article_list(request):
    # 从 url 中提取查询参数
    search = request.GET.get('search')
    order = request.GET.get('order')
    column = request.GET.get('column')
    tag = request.GET.get('tag')

    # 初始化查询集
    article_list = ArticlePost.objects.all()

    # 搜索查询集
    if search:
        article_list = article_list.filter(
            Q(title__icontains=search) |
            Q(body__icontains=search)
        )
    else:
        search = ''

    # 栏目查询集
    if column is not None and column.isdigit():
        article_list = article_list.filter(column=column)

    # 标签查询集
    if tag and tag != 'None':
        article_list = article_list.filter(tags__name__in=[tag])

    # 查询集排序
    if order == 'total_views':
        article_list = article_list.order_by('-total_views')

    paginator = Paginator(article_list, 3)
    page = request.GET.get('page')
    articles = paginator.get_page(page)
    
    # 需要传递给模板(templates)的对象
    context = {
        'articles': articles,
        'order': order,
        'search': search,
        'column': column,
        'tag': tag,
    }
    
    return render(request, 'article/list.html', context)

...

注意Django-taggit中 标签过滤 的写法: filter(tags__name__in=[tag]) ,意思是在 tags 字段中过滤 nametag 的数据条目。赋值的字符串 tag 用方括号包起来。

Model.objects.filter(tags__name__in=["tag1", "tag2"])

为了实现带参数的交叉查询,还要将 翻页 等位置的 href 修改一下:

templates/article/list.html

...

<!-- 所有类似地方加上 tag 参数,如 排序 、翻页等 -->

<a href="{% url 'article:article_list' %}?search={{ search }}&column={{ column }}&tag={{ tag }}">
    最新
</a>

...

<a href="{% url 'article:article_list' %}?order=total_views&search={{ search }}&column={{ column }}&tag={{ tag }}">
    最热
</a>

...

<a href="?page=1ℴ={{ order }}&search={{ search }}&column={{ column }}&tag={{ tag }}" class="btn btn-success">
    « 1
</a>

<!-- 上面3条是举例,其他类似地方也请补充进去 -->
...

标签过滤功能就完成了。

Django-taggit更多的用法请阅读官方文档: Django-taggit

总结

本章学习了使用Django-taggit来完成标签功能。

在学习阶段,你可以 不借助他人的轮子,自己实现功能 :瞎折腾对掌握基础有很大帮助。

实际开发时,又分为两种情况:

  • 浅层需求某项通用功能,开发完成后改动不大 :此类功能建议尽量使用轮子,加快开发效率。人生苦短,能节约的时间,一秒钟都不要浪费。
  • 需要大量定制化的功能,开发完成后需要频繁改动 :此类功能因为经常对底层代码进行改动,与其在别人的代码上修修补补,还不如自己从头写了。自己的代码不仅熟悉,而且都是为定制化而生的。

到底如何选择,就根据你的喜欢进行斟酌了。


以上所述就是小编给大家介绍的《Django搭建个人博客:文章标签功能》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Music Recommendation and Discovery

Music Recommendation and Discovery

Òscar Celma / Springer / 2010-9-7 / USD 49.95

With so much more music available these days, traditional ways of finding music have diminished. Today radio shows are often programmed by large corporations that create playlists drawn from a limited......一起来看看 《Music Recommendation and Discovery》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

html转js在线工具
html转js在线工具

html转js在线工具