Advertisement

Flask博客实战 - 实现文章列表页及详情页

阅读量:

在本系统中:
实现了分类列表页视图/category/int:cateid并对应的catelist.html模板
使用filter方法根据分类ID查询对应文章并分页展示
实现了文章详情页视图/category/int:cateid/int:postid并对应的detail.html模板
通过上一篇/下一篇逻辑展示了动态导航功能
在导航菜单中增加了分类路径的URL

实现分类列表页

在设计数据库字段结构时,我们将分类与文章归类为一对多的关系结构.这样每个分类下会有多个文章.由于上一节已实现这一点,本节的目标就是实现每个分类对应的动态列表页面.

在app/blog/views.py中实现分类页视图

复制代码
 @bp.route('/category/<int:cate_id>')

    
 def cates(cate_id):
    
     # 分类页
    
     cate = Category.query.get(cate_id)
    
     page = request.args.get('page', 1, type=int)
    
     pagination = Post.query.filter(Post.category_id==cate_id).paginate(page, per_page=10, error_out=False)
    
     post_list = pagination.items
    
     return render_template('cate_list.html', cate=cate, post_list=post_list, cate_id=cate_id, pagination=pagination)

这个函数的逻辑也是在之前开发管理后台功能时反复进行过实现。在这里我们采用了基于filter的方法,并根据传入的url中的分类主键id来查询对应的分类数据集,并对获取的结果进行分页处理。

生成该app/blog/templates目录下的cate_list.html模版文件

复制代码
 {% extends 'base.html' %}

    
  
    
 {% block title %}{{ cate.name }}{% endblock title %}
    
  
    
 {% block hero %}{% endblock hero %}
    
  
    
 {% block box %}
    
 <div class="columns">
    
     <div class="column is-9" style="border-right:solid 1px #eee ;">
    
     <div class="box is-shadowless has-background-light">
    
         {% block breadcrumb %}
    
         <nav class="breadcrumb is-small" aria-label="breadcrumbs">
    
             <ul>
    
             <li><a href="/">首页</a></li>
    
             <li class="is-active"><a href="#" aria-current="page">{{ cate.name }}</a></li>
    
             </ul>
    
         </nav>
    
         {% endblock breadcrumb %}
    
     </div>
    
  
    
     {% block cate_box %}
    
     {% for post in post_list %}
    
         <div class="pl-2">
    
             <h1 class="is-size-4">
    
                 <a href="{{ url_for('blog.detail', cate_id=post.category.id, post_id=post.id) }}">{{ post.title }}</a>
    
             </h1>
    
             <p class="has-text-grey-light is-size-6 mt-1">
    
                 <span class="icon"><i class="mdi mdi-clipboard-text-clock-outline"></i></span>{{ post.add_date }}
    
                 <span class="icon"><i class="mdi mdi-shape-outline"></i></span>{{ post.category.name }}
    
                 <span class="icon"><i class="mdi mdi-tag-heart-outline"></i></span>{{ post.tags|join(',') }}
    
             </p>
    
             <div class="has-text-grey mt-1">{{ post.desc }}</div>
    
         </div>
    
         <div class=" dropdown-divider mb-3"></div>
    
     {% endfor %}
    
     {% block pagination %}
    
     <nav class="pagination is-small" role="navigation" aria-label="pagination">
    
         {% if pagination.has_prev %}
    
         <a href="{{ url_for('blog.cates', cate_id=cate.id ) }}?page={{ pagination.prev_num }}" class="pagination-previous" title="This is the first page">Previous</a>
    
         {% endif %}
    
         {% if pagination.has_next %}
    
         <a href="{{ url_for('blog.cates', cate_id=cate.id) }}?page={{ pagination.next_num }}" class="pagination-next">Next page</a>
    
         {% endif %}
    
  
    
         <ul class="pagination-list">        
    
             {% for page in pagination.iter_pages() %}
    
                 {% if page %} 
    
                     {% if page != pagination.page %}
    
                     <li>
    
                         <a href="{{ url_for('blog.cates', cate_id=cate.id) }}?page={{ page }}" class="pagination-link" aria-label="Page 1" aria-current="page">{{ page }}</a>
    
                     </li>
    
                     {% else %}
    
                     <li>
    
                         <a class="pagination-link is-current" aria-label="Page 1" aria-current="page">{{ page }}</a>
    
                     </li>
    
                     {% endif %}
    
                 {% else %}
    
                     <span class=pagination-ellipsis>&hellip;</span>
    
                 {% endif %}
    
             {% endfor %}
    
  
    
         </ul>
    
     </nav>
    
     {% endblock pagination %}
    
     {% endblock cate_box %}
    
     </div>
    
     <div class="column">
    
     asdas
    
     </div>
    
 </div>
    
 {% endblock box %}

在该模板中,我们从刚才的视图中获取了返回的数据.此外,在继承base.html的基础上,我们实现了具有'一目了然'功能的样式表.

  • 最终样式

实现文章详情页

在app/blog/views.py中实现文章详情页视图

复制代码
 @bp.route('/category/<int:cate_id>/<int:post_id>')

    
 def detail(cate_id, post_id):
    
     # 详情页
    
     cate = Category.query.get(cate_id)
    
     post = Post.query.get_or_404(post_id)
    
  
    
     # 上一篇
    
     prev_post = Post.query.filter(Post.id < post_id).order_by(-Post.id).first()
    
     # 下一篇
    
     next_post = Post.query.filter(Post.id > post_id).order_by(Post.id).first()
    
  
    
     return render_template('detail.html', cate=cate, post=post, prev_post=prev_post, next_post=next_post)

这段代码不仅实现了文章详情页,还实现了上一篇及下一篇的功能!

经由url路径,我们依次获取了分类相关的cate_id标识符以及当前文章的post_id主键值。随后基于这两个关键参数信息,我们成功地检索到对应的分类信息及其相关文章内容。代码实现见下文

复制代码
 cate = Category.query.get(cate_id)

    
 post = Post.query.get_or_404(post_id)

在本系统中,开发团队综合完成了相关文章中的前一篇及后一篇功能,并通过当前文章的id来判断筛选出上一篇和下一篇内容.代码如下:

复制代码
 # 上一篇

    
 prev_post = Post.query.filter(Post.id < post_id).order_by(-Post.id).first()
    
 # 下一篇
    
 next_post = Post.query.filter(Post.id > post_id).order_by(Post.id).first()

在app/blog/templates/中创建一个detail.html的模板文件

复制代码
 {% extends 'cate_list.html' %}

    
  
    
 {% block title %}
    
     {{ post.title }}
    
 {% endblock title %}
    
  
    
 {% block breadcrumb %}
    
     <nav class="breadcrumb is-small" aria-label="breadcrumbs">
    
     <ul>
    
         <li><a href="/">首页</a></li>
    
         <li><a href="{{ url_for('blog.cates', cate_id=cate.id) }}">{{ cate.name }}</a></li>
    
         <li class="is-active"><a href="#" aria-current="page">{{ post.title }}</a></li>
    
     </ul>
    
     </nav>
    
 {% endblock breadcrumb %}
    
  
    
 {% block cate_box %}
    
 <div class="pl-2">
    
     <h1 class="is-size-3">
    
     {{ post.title }}
    
     </h1>
    
     <p class="has-text-grey-light is-size-6 mt-1">
    
     <span class="icon"><i class="mdi mdi-clipboard-text-clock-outline"></i></span>{{ post.add_date }}
    
     <span class="icon"><i class="mdi mdi-shape-outline"></i></span>{{ post.category.name }}
    
     <span class="icon"><i class="mdi mdi-tag-heart-outline"></i></span>{{ post.tags|join(',') }}
    
     </p>
    
     <div class="content has-text-grey mt-1">{{ post.content|safe }}</div>
    
 </div>
    
  
    
 <hr>
    
 <div class="level">
    
     <div class="level-left">
    
     {% if prev_post %}
    
         上一篇:<a href="{{ url_for('blog.detail', cate_id=prev_post.category.id, post_id=prev_post.id) }}">{{ prev_post.title }}</a>
    
     {% endif %}
    
     </div>
    
     <div class="level-right">
    
     {% if next_post %}
    
         下一篇:<a href="{{ url_for('blog.detail', cate_id=next_post.category.id, post_id=next_post.id) }}">{{ next_post.title }}</a>
    
     {% endif %}
    
     </div>
    
 </div>
    
 {% endblock cate_box %}

增加导航菜单中的url

路径: app/blog/templates/base.html

复制代码
 {% for cate in categorys %}

    
     <b-navbar-item
    
     {% if cate.id == cate_id %}class="has-text-primary"{% endif %} 
    
     href="{{ url_for('blog.cates', cate_id=cate.id) }}">
    
     {{ cate.name }}
    
     </b-navbar-item>
    
 {% endfor %}

首页文章url完善

路径: app/blog/templates/base.html

复制代码
 {% for post in posts %}

    
 <div class="column is-4-fullhd is-6-desk">
    
     <div class="card">
    
     <div class="card-image">
    
         <figure class="image is-4by5">
    
             <img src="{{ post.img }}" alt="Placeholder image">
    
         </figure>
    
     </div>
    
     <div class="card-content">
    
         <div class="content">
    
             <p class="title is-4"><a
    
                     href="{{ url_for('blog.detail', cate_id=post.category.id, post_id=post.id) }}">{{ post.title}}</a> </p>
    
             <p class="has-text-grey subtitle is-size-6">
    
                 {{ post.desc }}
    
             </p>
    
             <time class="has-text-grey" datetime="{{ post.add_date }}">{{ post.add_date }}</time>
    
         </div>
    
     </div>
    
     </div>
    
 </div>
    
 {% endfor %}

全部评论 (0)

还没有任何评论哟~