利用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>