Flask分页方法

当博客文章达到一定数量的时候,把它们都放在同一个列表页面不是一个明智的选择,因为这样会使页面过大从而影响加载速度,影响读者的阅读体验。所以我们需要一个粉页的功能。在网上搜索了一下,大部分关于Flask的分页都基于SQLAlchemy,但是我们并不是通过数据库来管理文件的。我们需要一种更为通用的方法,构建我们自己的切片方法并设置正确的路由。

切片

首先我们需要对文章列表进行切片,在这里我们声明一个Pagination的类来获得不同部分的文章列表

1
2
import math
class Pagination(object):

Pagination需要三个参数,分别是:

  • page 当前页面页码
  • per_page 每页显示数目
  • 文章列表(需要被切片的对象),使用len可获得总文章数

    1
    2
    3
    4
    5
    def __init__(self,page,per_page,iterable):
    self.page = page
    self.per_page = per_page
    self.iterable = iterable
    self.total = len(iterable)

之后我们通过定义类方法来获得

  • 页面总数

    1
    2
    3
    @property
    def total_pages(self):
    return int(math.ceil(self.total/self.per_page))
  • 是否有”上一页/下一页”,如果有返回True,否则False

    1
    2
    3
    4
    5
    6
    7
    @property
    def has_prev(self):
    return self.page > 1

    @property
    def has_next(self):
    return self.page < self.total_pages
  • 页码列表

    1
    2
    3
    4
    @property
    def pager(self):
    #返回[1,2,3,...,n]
    return list(range(1,self.total_pages+1))
  • 切片后的当前页面列表

    1
    2
    3
    4
    5
    6
    7
    8
    @property
    def items(self):
    index = self.page - 1
    start = index * self.per_page
    end = start + self.per_page
    #如果当前第二页,每页6篇文章
    #则会返回第7-12篇文章的列表
    return self.iterable[start:end]
  • 切片后的当前页面列表

路由

  • 设置路由

    1
    2
    3
    @postwall.route('/posts')#默认第一页路径为http://你的网站/posts
    @postwall.route('/posts/page/<int:page>/')#从第二页开始的路径
    def posts(page = 1):#page = 1是默认第一页的时候page为1

其中page参数与‘int:page’对应,是页码的参数,并作为参数传入Pagination类

  • 使用Pagination类切片

    1
    2
    PER_PAGE = 6
    page_list = Pagination(page,PER_PAGE,sorted_posts)
  • 将切片后的对象返回给模板:

    1
    return render_template('posts.html',pagination = page_list)

在使用分页之前,由于我们只需要将所有页码加入到主页当中,所以我们只需要将文章列表传入模板,而现在我们使用了切片的Pagination类,这时候传入模板的是一个类对象而不是列表

模板生成

首先我们先创建一个模板的Marco模块pagination.html来表示我们生成页码的过程,pagination就是我们通过路由引入的切片后的类对象

‘pagination = page_list‘

第一行定义macro

{% macro pager(pagination) %}
在网页中创建一个分页区块

		
	{% endmacro %}