目录
前言
分页操作在web开发中几乎是必不可少的,而我们的flask不像django自带封装好的分页操作,要分页则需要依赖flask-sqlalchemy中的分页查询,但是分页这么重要且简单的操作,自己实现必须要会这个思维,我也在网上看了一些,但大体上不合我意,因此这篇我带大家手写一个分页操作!
后端
后端思路
写这个分页操作前我们首先要思考我们需要什么?我们需要将我们需要的东西封装到一个字典里,然后传给前端!那么这里我先说分页算法,很简单!
有两个核心:总页数,偏移量
total_pages = math.ceil(totals / page_size)
数据总条数/每一页的数据,然后向上取整,就是我们当前的总页数!
偏移量是我们数据查询时从那条数据开始获取我们的当前数据,比如每页有十条数据,我们要取第二页的数据(即11-20条数据),这里偏移量就是10,相当于从第十条数据开始(不包含10),查询十条数据(sql里的limit)!
那么这个偏移量算法:
offset = (current_page – 1) * page_size
当前页页码减一,然后乘上每页的数据即是我们的偏移量。
这两个核心是分页操作的关键,但在具体实现上还需要加一些判断!
除了这些,你在想想你还需要把那些参数封装到字典里传给前端,加入进去就可以!
- 上一页,下一页
- 每页多少条数据
- 当前页码
- 最大页码
- 数据总条数
- 页码范围
- ···
后端代码
def Pagination(page_num,totals): ret = {\"prev_page\": page_num - 1, # 上一页 \"next_page\": page_num + 1, # 下一页 \"current_page\": 0, # 当前页 \"total_pages\": 0, # 总页数 \"max_page\": 0, # 最大页 \"page_size\": app.config[\"PAGE_SIZE\"], # 每页的数据,放在配置中方便更改 \"totals\": totals, # 数据总条数 \"offset\": 0, # 偏移量 \"page_range\": None # 页码范围 } ret[\"total_pages\"] = math.ceil(totals / ret[\"page_size\"]) ret[\"max_page\"] = ret[\"total_pages\"] if page_num <= 1: page_num = 1 ret[\"prev_page\"] = 1 if page_num >= ret[\"max_page\"]: page_num = ret[\"max_page\"] ret[\"next_page\"] = ret[\"max_page\"] ret[\"current_page\"] = page_num if totals == 0: ret[\"offset\"] = 0 else: ret[\"offset\"] = (ret[\"current_page\"] - 1) * ret[\"page_size\"] page_range = [] for i in range(1,ret[\"max_page\"]+1): page_range.append(i) ret[\"page_range\"] = page_range return ret
使用它只需将请求页码和数据总条数传进去就可以了!
我们来看视图操作:
@app.route(\"/index\") def index(): page_num = int(request.args.get(\"page\",1)) query = User.query # 分页 totals = query.count() pagination = Pagination(page_num, totals) if totals != 0: data_list = query.offset(pagination[\"offset\"]).limit(pagination[\"page_size\"]).all() else: data_list = [] pagination[\"data_list\"] = data_list return render_template(\"account/index.html\",pagination=pagination)
现在一看绝对清晰了吧,不急,看完前端你会更清晰!
前端
前端思路
我们python项目对于 jinjia2 还是有依赖性的,就我个人而言,他可以帮助我们简化复杂的 javascript 操作,便于数据展示,对于这个分页也是如此!
对于这个分页,则是要依赖后端传过来的页码范围page_range,这是一个列表,里面放的是我们的所有页码,我们只需要循环展示这些页码供用户点击就行,当循环展示的页码等于当前页时变个色就行!
思路就是这样没有问题,网上也基本就是这么做的!
但这样做有一个问题,就是如果你的数据页数很多,难道你要全部循环展示吗,基本都超出页面了!
对于解决这个问题最简单的方法就是设置一个页码阈值,(我直接在前端写数字了,你可以在后端封装到分页的 ret 字典里或者写到flask配置中,便于更改),当总页数大于这个阈值时,不循环展示页码,在上一页和下一页中间展示一个省略号就行!
前端代码
ui框架用的bootstrap
<!--分页代码--> <div class=\"row\"> <div class=\"col-lg-12\"> <span class=\"pagination_count\" style=\"line-height: 40px;\">共{{ pagination.totals }}条数据 | {{ pagination.total_pages }}页</span> <ul class=\"pagination pagination-sm no-margin pull-right\"> <li><a href=\"{{ url_for(\'food_page.index\') }}?page={{ pagination.prev_page }}\">«</a></li> {% if pagination.total_pages <= 15 %} {% for k in pagination.page_range %} {% if pagination.current_page == k %} <li class=\"active\"><a href=\"{{ url_for(\'food_page.index\') }}?page={{ k }}\">{{ k }}</a></li> {% else %} <li><a href=\"{{ url_for(\'food_page.index\') }}?page={{ k }}\">{{ k }}</a></li> {% endif %} {% endfor %} {% else %} <li><a href=\"javascript:void(0);\">...</a></li> {% endif %} <li><a href=\"{{ url_for(\'food_page.index\') }}?page={{ pagination.next_page }}\">»</a></li> </ul> </div> </div>
暂无评论内容