• Flask博客实战 - 实现侧边栏文章归档及标签


    按照正常的博客网站布局,一般都会存在侧边栏,侧边栏比较常见的几个模块分别是 搜索、最新文章、文章归档、标签等!该教程会带大家实现这四个模块!

    按照当前项目的布局,我们的侧边栏仅在blog应用中的页面展示,也就是博客的列列表页和详情页展示,那么这个视图是通过blog中的蓝图绑定的,因此我们在左侧边栏的时候只需要针对这个应用即可!

    • 最终的效果

    实现文章归档功能

    在app/blog/views.py中通过博客的蓝图注入上下文,代码如下

    1. @bp.context_processor
    2. def inject_archive():
    3. # 文章归档日期注入上下文
    4. posts = Post.query.order_by(Post.add_date)
    5. dates = set([post.add_date.strftime("%Y年%m月") for post in posts])
    6. # 标签
    7. tags = Tag.query.all()
    8. for tag in tags:
    9. tag.style = ['is-success', 'is-danger', 'is-black', 'is-light', 'is-primary', 'is-link', 'is-info', 'is-warning']
    10. return dict(dates=dates, tags=tags)

    首先我们这里选择按月归档的方式,也就是把每个月的文章归类到一起,那么我们就必须先把年月查询显示到侧边栏,代码如下:

    1. posts = Post.query.order_by(Post.add_date)
    2. dates = set([post.add_date.strftime("%Y年%m月") for post in posts])

    首先查询出所有的文章并按照发布时间倒叙排列,也就是最新发布的文章在最前边,之后再提取出每篇文章的发布日期的年月,使用strftime方法格式化成我们需要的格式,并使用set简单去重,并返回到上下文!

    实现文章归档的详情视图

    1. @bp.route('/category/<string:date>')
    2. def archive(date):
    3. # 归档页
    4. import re
    5. # 正则匹配年月
    6. regex = re.compile(r'\d{4}|\d{2}')
    7. dates = regex.findall(date)
    8. from sqlalchemy import extract, and_, or_
    9. page = request.args.get('page', 1, type=int)
    10. # 根据年月获取数据
    11. archive_posts = Post.query.filter(and_(extract('year', Post.add_date) == int(dates[0]), extract('month', Post.add_date) == int(dates[1])))
    12. # 对数据进行分页
    13. pagination = archive_posts.paginate(page, per_page=10, error_out=False)
    14. return render_template('archive.html', post_list=pagination.items, pagination=pagination, date=date)

    详情视图我们通过url传递进来要访问的日期,并通过正则表达式提取出年和月,代码如下:

    1. import re
    2. # 正则匹配年月
    3. regex = re.compile(r'\d{4}|\d{2}')
    4. dates = regex.findall(date)

    下边这段代码引入了sqlalchemy提供extract, and_两个方法,extract用来提取某个字段的值,and_实现两个并且的关系,然后根据正则获取的 年月匹配查询出当月的文章!

    1. from sqlalchemy import extract, and_, or_
    2. archive_posts = Post.query.filter(and_(extract('year', Post.add_date) == int(dates[0]), extract('month', Post.add_date) == int(dates[1])))

    其他代码都是在之前的章节中多次使用,大家自行理解!

    创建归档页模板,在app/blog/templates/中创建archive.html,代码如下:

    1. {% extends 'cate_list.html' %}
    2. {% block title %}{{ date }}的文章归档 {% endblock title %}
    3. {% block hero %}{% endblock hero %}
    4. {% block breadcrumb %}
    5. <nav class="breadcrumb is-small" aria-label="breadcrumbs">
    6. <ul>
    7. <li><a href="/">首页</a></li>
    8. <li class="is-active"><a href="#" aria-current="page">{{ date }}的归档</a></li>
    9. </ul>
    10. </nav>
    11. {% endblock breadcrumb %}
    12. {% block pagination %}
    13. <nav class="pagination is-small" role="navigation" aria-label="pagination">
    14. {% if pagination.has_prev %}
    15. <a href="{{ url_for('blog.archive', date=date ) }}?page={{ pagination.prev_num }}" class="pagination-previous" title="This is the first page">Previous</a>
    16. {% endif %}
    17. {% if pagination.has_next %}
    18. <a href="{{ url_for('blog.archive', date=date) }}?page={{ pagination.next_num }}" class="pagination-next">Next page</a>
    19. {% endif %}
    20. <ul class="pagination-list">
    21. {% for page in pagination.iter_pages() %}
    22. {% if page %}
    23. {% if page != pagination.page %}
    24. <li>
    25. <a href="{{ url_for('blog.archive', date=date) }}?page={{ page }}" class="pagination-link" aria-label="Page 1" aria-current="page">{{ page }}</a>
    26. </li>
    27. {% else %}
    28. <li>
    29. <a class="pagination-link is-current" aria-label="Page 1" aria-current="page">{{ page }}</a>
    30. </li>
    31. {% endif %}
    32. {% else %}
    33. <span class=pagination-ellipsis>&hellip;</span>
    34. {% endif %}
    35. {% endfor %}
    36. </ul>
    37. </nav>
    38. {% endblock pagination %}

    实现文章标签功能

    函数中的代码如下:

    1. # 标签
    2. tags = Tag.query.all()
    3. for tag in tags:
    4. tag.style = ['is-success', 'is-danger', 'is-black', 'is-light', 'is-primary', 'is-link', 'is-info', 'is-warning']

    这个就非常简单直接查询出所有的标签即可,这里额外新增了一个style的属性,是配合前端显示不同的颜色!

    实现标签详情视图

    1. @bp.route('/tags/<int:tag_id>')
    2. def tags(tag_id):
    3. # 标签页
    4. tag = Tag.query.get(tag_id)
    5. return render_template('tags.html', post_list=tag.post, tag=tag)

    创建标签页模板,在app/blog/templates/中创建tags.html,代码如下:

    1. {% extends 'cate_list.html' %}
    2. {% block title %}{{ tag }} {% endblock title %}
    3. {% block hero %}{% endblock hero %}
    4. {% block breadcrumb %}
    5. <nav class="breadcrumb is-small" aria-label="breadcrumbs">
    6. <ul>
    7. <li><a href="/">首页</a></li>
    8. <li class="is-active"><a href="#" aria-current="page">{{ tag }}</a></li>
    9. </ul>
    10. </nav>
    11. {% endblock breadcrumb %}
    12. {% block pagination %}
    13. {% endblock pagination %}

    模板中新增侧边栏模块

    在app/blog/templates/cate_list.html中我们预留的右侧块中新增如下代码

    1. <div class="box is-shadowless" style="border:solid 1px #eee ;">
    2. <h1 class="is-size-6 icon-text">
    3. <span class="icon"><i class="mdi mdi-calendar-month-outline"></i></span>
    4. 归档
    5. </h1>
    6. <div class=" dropdown-divider"></div>
    7. <ul>
    8. {% for date in dates %}
    9. <li class="pl-2"><a href="{{ url_for('blog.archive', date=date) }}">{{ date }}</a></li>
    10. <div class="dropdown-divider"></div>
    11. {% endfor %}
    12. </ul>
    13. </div>
    14. <div class="box is-shadowless" style="border:solid 1px #eee ;">
    15. <h1 class="is-size-6 icon-text">
    16. <span class="icon"><i class="mdi mdi-tag-multiple-outline"></i></span>
    17. 标签
    18. </h1>
    19. <div class=" dropdown-divider"></div>
    20. {% for tag in tags %}
    21. <div class="tags">
    22. <a class="tag {{ tag.style|random() }}" href="{{ url_for('blog.tags', tag_id=tag.id) }}">{{ tag.name }}</a>
    23. </div>
    24. {% endfor %}
    25. </div>

    到这里我们侧边栏两个简单的模块就完成了,下一章节我们将实现搜索和最新文章两个模块!

     

  • 相关阅读:
    【druid】Connection Close的问题,通过配置Druid的泄露检测机制解决
    Webservice接口-WSDL文档【Webservice】
    激光、超声波、霍尔、DS18B20 温度、模拟温度传感器 | 配合Arduino使用案例
    关于mac上如何U盘
    C#.Net筑基-模式匹配汇总
    mysql之子表查询、视图、连接查询
    java计算机毕业设计高校大学生就业系统MyBatis+系统+LW文档+源码+调试部署
    字节也开始缩招了...
    第一章 C语言程序设计Pro
    TS编译器选项——指定编译ES版本和模块化使用规范
  • 原文地址:https://blog.csdn.net/weixin_41861301/article/details/125410926