10. 爬虫训练场,分页爬虫案例前端页面制作

举报
梦想橡皮擦 发表于 2023/02/23 17:16:35 2023/02/23
【摘要】 本篇博客重点在分页逻辑与前端页面渲染实现,如果不是顺序阅读过来,可以先查看上一篇博客 Python Flask 分页实现实现 Python Flask 分页会涉及如下参数值。总页数:计算总页码使用当前页:获取数据使用偏移量:计算下一页数据起点除了重要参数外,实现一个分页对象还需要如下参数变量。 page_obj = { "prev_page": page - 1, ...

本篇博客重点在分页逻辑与前端页面渲染实现,如果不是顺序阅读过来,可以先查看上一篇博客

Python Flask 分页实现

实现 Python Flask 分页会涉及如下参数值。

  • 总页数:计算总页码使用
  • 当前页:获取数据使用
  • 偏移量:计算下一页数据起点

除了重要参数外,实现一个分页对象还需要如下参数变量。

    page_obj = {
        "prev_page": page - 1,
        "next_page": page + 1,
        "current_page": 0,
        "total_page": 0,
        "max_page": 0,
        "page_size": 20,
        "total": total,
        "offset": 0,
        "page_range": None
    }

其中 pagetotal 通过外部传递,page_size 为单页数据量,可以硬编码,也可以通过配置文件进行读取。

接下来就先实现分页函数逻辑,示例代码如下。

def Pagination(page, total):
    """
    Pagination 用于封装分页参数到字典变量中,并返回到前台
    :param page: 传入参数,页码
    :param total: 数据总量
    :return:
    """
    page_obj = {
        "prev_page": page - 1,
        "next_page": page + 1,
        "current_page": 0,
        "total_page": 0,
        "max_page": 0,
        "page_size": 20,
        "total": total,
        "offset": 0,
        "page_range": None
    }

    page_obj["total_page"] = math.ceil(total / page_obj["page_size"])
    page_obj["max_page"] = page_obj["total_page"]

    if page <= 1:
        page = 1
        page_obj["prev_page"] = 1

    if page >= page_obj["max_page"]:
        page = page_obj["max_page"]
        page_obj["next_page"] = page_obj["max_page"]

    page_obj["current_page"] = page

    if total == 0:
        page_obj["offset"] = 0
    else:
        page_obj["offset"] = (page_obj["current_page"] - 1) * page_obj["page_size"]

    page_range = []
    for i in range(1, page_obj["max_page"] + 1):
        page_range.append(i)
    page_obj["page_range"] = page_range

    return page_obj

total_page 是总页码,需要进行向下取整,所以使用 math.ceil() 函数,获得该值之后,在将其赋值给 max_page,对于第一页和最后一页的逻辑,参考下述代码即可。

    if page <= 1:
        page = 1
        page_obj["prev_page"] = 1

    if page >= page_obj["max_page"]:
        page = page_obj["max_page"]
        page_obj["next_page"] = page_obj["max_page"]

偏移量参数为 offset,其计算表达式为 (page_obj["current_page"] - 1) * page_obj["page_size"],即(当前页-1)*每页的数据量,如果总数量为 0,偏移量默认也设置为 0 。

最后一段代码设置的是页码范围,用于后续展示页码数字

    page_range = []
    for i in range(1, page_obj["max_page"] + 1):
        page_range.append(i)
    page_obj["page_range"] = page_range

Python Flask 分页控制器实现

分页函数编写完毕,就可以实现控制器函数的升级了,代码如下所示,这里修改的是 app/school/index.py 文件代码。

@s.route('/list')
def list_school():
    # schools = School.query.all()
    page = int(request.args.get("page",1)) # 获取页码
    query = School.query

    total = query.count() # 获取数据总量
    pagination = Pagination(page, total) # 获取分页对象详细参数

    if total != 0:
        data_list = query.offset(pagination["offset"]).limit(pagination["page_size"]).all()
    else:
        data_list = []
    pagination["data_list"] = data_list

    return render_template('school/index.html', pagination=pagination)

上述代码首先通过 request.args.get("page",1) 获取用户请求页码,然后在通过 query 对象分别获取总数据和数据对象清单 data_list。最后将数据组合到 pagination 对象中,便于传递到前端页面进行渲染。

前端分页组件实现

控制器部分代码编写完毕,就可以编写前端分页组件了,这里前端渲染使用的是 Bootstrap 和 Python jinjia2 模块,示例代码如下。

<div class="row">
  <div class="col">
    <span class="pagination_count">合计 {{pagination.total}} 条数据</span>
    <ul class="pagination pagination-sm no-margin pull-right">
      <li>
        <a href="{{url_for('school.list_school')}}?page={{pagination.prev_page }}">上一页</a>
      </li>

      {% for p in pagination.page_range %} {% if pagination.current_page == p %}
      <li class="active">
        <a href="{{ url_for('school.list_school') }}?page={{ p }}">{{ p }}</a>
      </li>
      {% else %}
      <li>
        <a href="{{ url_for('school.list_school') }}?page={{ p }}">{{ p }}</a>
      </li>
      {% endif %} {% endfor %}
      <li>
        <a href="{{ url_for('school.list_school') }}?page={{ pagination.next_page }}">下一页</a>
      </li>
    </ul>
  </div>
</div>

结果预览页面之后发现所有的页码都被罗列出来了,效果如下。

image.png

这样的分页非常难看,我们需要针对性的处理,即隐藏部分页码,这里简单处理,我们仅展示上一页和下一页。

<div class="container">
    <div class="row">
        <div class="col">
            <span class="text-dark float-end align-middle" style="line-height: 40px;">合计  {{pagination.total}} 条数据</span>
            <ul class="pagination float-end">
                <li class="page-item">
                    <a class="page-link" href="{{url_for('school.list_school')}}?page={{pagination.prev_page }}">上一页</a>
                </li>
                <li class="page-item"><a class="page-link"
                                         href="{{ url_for('school.list_school') }}?page={{ pagination.next_page }}">下一页</a>
                </li>
            </ul>
        </div>
    </div>
</div>

最终得到的效果图如下所示,并且点击分页,地址已经发生变化。
image.png

📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中指正吧
📆 橡皮擦的第 806 篇原创博客

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。