利用Flask-SQLAlchemy提供的paginate()方法实现博客文章的分页显示

在开发blog系统的时候,我们有一个需求,就是要显示作者已经发表的blog文章的列表,或显示作者关注者的文章列表。实现这个功能并不复杂,只需要在存储文章的数据库中过滤出指定作者的文章,然后渲染HTML显示即可。 
但是,这种方法在文章不多的情况下或许是可行的,当文章的数量变多的时候,就无法在一页中显示完所有的文章了。这时就需要将文章列表进行分页显示,每一页只显示指定数量的文章。 
这个功能应该如何实现呢?我们能想到的一个直观的方法就是将从数据库中过滤得到的文章列表进行分组,每次只显示一组文章。然后根据用户的需要来显示指定组的文章列表。 
俗话说:Talk is cheap ,show me the code .以上这些该如何落实到代码中呢?Flask-SQLAlchemy可以祝我们一臂之力。Flask-SQLAlchemy提供的paginate()方法可以实现按照指定的数量来对从数据库中得到的文章列表进行分组。那么有了文章列表的分组,我们该如何指定显示哪个分组呢?这就需要在HTML页面中添加一个分页导航栏了,有了这个分页导航栏,用户就可以根据需要显示指定的文章列表分组了。那么这个分页导航栏又该如何实现呢?让我们还是回到Flask-SQLAlchemy提供的paginate()方法中来,paginate()方法的返回值是一个Pagination类对象,这个类在Flask-SQLAlchemy中定义。这个类包含很多的属性,可以用来在模板中生成分页的链接,因此可以将其作为参数传入模板。 
Pagination类对象的属性主要有: 
has_next:如果在目前页后至少还有一页的话,返回 True。 
has_prev:如果在目前页之前至少还有一页的话,返回 True。 
next_num:下一页的页面数。 
prev_num:前一页的页面数。 
另外还有如下的可调用方法: 
iter_pages():一个迭代器,返回一个在分页导航中显示的页数列表。 
prev():上一页的分页对象。 
next():下一页的分页对象。 
关于Pagination类对象的属性和方法的详细介绍, 
请参考 
下面让我们先看一看如何将过滤得到的文章列表进行分组。 
假设我们的文章存储在post表中,在ORM中的名字是Post。

@main.route('/', methods=['GET', 'POST'])
def index():
    page = request.args.get('page', 1, type=int)    
    pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page,per_page=current_app.config['ARTISAN_POSTS_PER_PAGE'],error_out=False)
    posts = pagination.items
    return render_template('index.html', form=form, posts=posts,                          pagination=pagination)

在Bootstrap中有分页的css类,我们可以利用这个类在模板中构建分页导航,利用jinjia2宏的形式实现的分页导航代码如下:

<ul class="posts">
    {% for post in posts %}
    <li class="post">
        <div class="post-thumbnail">
            <a href="{{ url_for('.user', username=post.author.username) }}">
                 <img class="img-rounded profile-thumbnail" src="{{ post.author.image }}">
            </a>
        </div>
        <div class="post-content">
            <div class="post-date">{{ moment(post.timestamp).fromNow() }}</div>
            <div class="post-author"><a href="{{ url_for('.user', username=post.author.username) }}">{{ post.author.username }}</a></div>
            <div class="post-body">
                {% if post.body_html %}
                    {{ post.body_html | safe }}
                 {% else %}
                     {{ post.body }}
                {% endif %}
            </div>
            <div class="post-footer">
                {% if current_user == post.author %}
                <a href="{{ url_for('.edit',id=post.id)}}">
                    <span class="label label-primary">Edit</span>
                </a>
                {% elif current_user.is_adminstrator() %}
                 <a href="{{ url_for('.edit',id=post.id)}}">
                    <span class="label label-primary">Edit [Admin]</span>
                 </a>
                {% endif %}
                <a href="{{ url_for('.post',id=post.id) }}">
                    <span class="label label-default">Permalink</span>
                </a>
            </div>
        </div>
    </li>
    {% endfor %}
</ul>

在主页中显示导航栏的代码如下:、

<div class="pagination">
    {{ macros.pagination_widget(pagination, '.index') }}
</div>

  

posted @ 2018-09-13 21:11  核电站  阅读(2304)  评论(0编辑  收藏  举报