【flask进阶】Flask实现自定义分页(python web通用)

📋 个人简介

  • 💖 作者简介:大家好,我是阿牛,全栈领域新星创作者。😜
  • 🎉 支持我:点赞👍+收藏⭐️+留言📝
  • 📣 系列专栏:flask框架快速入门🍁
  • 💬格言:要成为光,因为有怕黑的人!🔥
    请添加图片描述

  • 目录

  • 📋 个人简介
  • 前言
  • 后端
  • 后端思路
  • 后端代码
  • 前端
  • 前端思路
  • 前端代码
  • 结语
  • 前言

    分页操作在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 }}">&laquo;</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 }}">&raquo;</a></li>
          </ul>
        </div>
    </div>
    

    结语

    如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。

    🏰系列专栏
    👉软磨 css
    👉硬泡 javascript
    👉前端实用小demo

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【flask进阶】Flask实现自定义分页(python web通用)

    发表评论