分页是一个很常见的功能了,尤其是当数据达到一定量的时候,如果都显示在页面上,会造成页面过长而影响用户体验,除此之外,还可能出现加载过慢等问题。因此,分页就很有必要了。
这是分页的效果图,数据都是从MySQL数据库中取出来的。
分页代码
from flask import Flask,render_template,request
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
#连接数据库
HOSTNAME = '127.0.0.1'
PORT = '3306'
DARABASE = ''
USERNAME = ''
PASSWORD = ''
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DARABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
@app.route('/movie')
def movie():
db.reflect()
#获取所有数据表
all_table={table_obj.name: table_obj for table_obj in db.get_tables_for_bind()}
#定位movies表
data=db.session.query(all_table['movies'])
#当前页码,从第一页开始
page = int(request.args.get("page", 1))
#每页的数量
per_page = int(request.args.get('per_page', 25))
paginate = data.paginate(page, per_page, error_out=False)
movies = paginate.items
return render_template("movie.html",movies=movies, paginate=paginate)
paginate 是一个SQLAlchemy中的Pagination类型对象。paginate方法传入了两个参数,一个page是当前页,另一个per_page是每一页最多显示多少条数据。
前端代码
{% if paginate %}
<ul class="pagination pagination-sm no-margin pull-right">
<li><a href="/movie?page=1">首页</a></li>
{% if paginate.has_prev %}
<li class="active"><a href="/movie?page={{ paginate.prev_num }}">上一页</a></li>
{% else %}
<li class="disabled"><a href="">上一页</a></li>
{% endif %}
{% for v in paginate.iter_pages(1,1,3,1) %} <!--iter_pages 是一个迭代器 返回分页栏上的页码数 如果显示不下 返回None-->
{% if v %} <!--iter_pages(left_edge=2,left_current=2,right_current=5,right_edge=2)里面默认参数,左边边缘显示2个,右边边缘显示2个,当前页码左边显示2个,当前页码右边显示5个-->
{% if v==paginate.page %}
<li class="active"><a href="#">{{ v }}</a></li> <!--显示当前页数-->
{% else %}
<li><a href="/movie?page={{ v }}">{{v}}</a></li> <!--显示除当前页数的其他页数-->
{% endif %}
{% else %}
<li class="disabled"><a href="">…</a></li> <!--把显示None变成省略号-->
{% endif %}
{% endfor %}
{% if paginate.has_next %}
<li class="active"><a href="/movie?page={{ paginate.next_num }}">下一页</a></li>
{% else %}
<li class="disabled"><a href="">下一页</a></li>
{% endif %}
<li><a href="/movie?page={{ paginate.pages }}">尾页</a></li>
</ul>
{% endif %}
Pagination对象的常用属性有:
- prev_num 上一页页码
- next_num 下一页页码
- has_next 是否有下一页 True/False
- has_prev 是否有上一页 True/False
- pages 查询得到的总页数
- total 总的记录条数
iter_pages 是一个迭代器 返回分页栏上的页码数 如果显示不下 返回None。iter_pages(left_edge=2,left_current=2,right_current=5,right_edge=2)里面默认参数,左边边缘显示2个,右边边缘显示2个,当前页码左边显示2个,当前页码右边显示5个
分析一下上述页面代码:
1,整体来说就是根据当前对“上一页”,“页码”和“下一页”进行不同的设置
2,使用JinJa2的宏,定义page方法,传入路径和pagination对象作为参数。通过调用宏的执行生成分页内容。
3,利用JinJa2的if语句根据当前页是否还有前一页使用不同的元素。
4,如果当前页有上一页,则pagination对象的has_prev为True,此时li标签的class为active,为此时上一页是可点的。
5,如果当前页没有上一页,则pagination对象的has_prev为False,此时li标签的class为disable,为此时上一页是不可点的。跳转的链接会是#
6,与“上一页”处理类似的是对“下一页”的处理。如果当前页有下一页时设置样式和点击跳转路径,如果没有下一页了,则设置为不可点击并且跳转路径为#
7,利用iter_pages(1,1,3,1)会获得基于当前页应该显示的页码列表。如上面截图所示,如果当前页是第4页,获得的分页列表内容就是[1,None,3,4,5,6,None,10],如果当前页是第10页,获得的分页列表内容是[1,None,9,10]
8,利用JinJa2的for语句遍历列表,如果是页码,就根据页码生成a标签中的文字并设置跳转路径并添加上page参数。如果是None,a标签中的文字为实体名表示的省略号,路径为“#”。额外的,如果遍历时获得了当前页码所对应的数字时,为li标签的class属性添加上额外的active以获得额外的样式。
参考网址:https://zhuanlan.zhihu.com/p/94353052
这些都是基础知识及用法,如果想要了解更多的分页的知识和用法,请查看Pagination中文手册https://cloud.tencent.com/developer/section/1489889。