• Django高级之-分页器


    目录

    一、引入

    二、分页推导

    三、数据总页面获取

    四、内置方法之divmod

    五、终极大法

    六、自定义分页器使用

    【1】后端

    【2】前端


    一、引入

    • 针对上一小节批量插入的数据
      • 我们在前端展示的时候发现一个很严重的问题
      • 一页展示了所有的数据,数据量太大,查看不方便
    • 针对数据量大但又需要全部展示给用户观看的情况下
      • 我们统一做法都是做分页处理

    二、分页推导

    • 首先我们需要明确的时候
      • get请求也是可以携带参数的
      • 所以我们在朝后端发送查看数据的同时可以携带一个参数告诉后端我们想看第几页的数据
    • 其次我们还需要知道一个点
      • queryset对象是支持索引取值和切片操作的
      • 但是不支持负数索引情况
    • 接下来我们就可以推导我们的自定义分页器步骤了
    1. current_page = request.GET.get("page",1) # 获取用户想访问的页码 如果没有 默认展示第一页
    2. try: # 由于后端接受到的前端数据是字符串类型所以我们这里做类型转换处理加异常捕获
    3. current_page = int(current_page)
    4. except Exception as e:
    5. current_page = 1
    6. # 还需要定义页面到底展示几条数据
    7. per_page_num = 10 # 一页展示10条数据
    8. # 需要对总数据进行切片操作 需要确定切片起始位置和终止位置
    9. start_page = ?
    10. end_page = ?
    1. 下面需要研究current_page、per_page_num、start_page、end_page四个参数之间的数据关系
    2. per_page_num = 10
    3. current_page start_page end_page
    4. 1 0 10
    5. 2 10 20
    6. 3 20 30
    7. 4 30 40
    8. per_page_num = 5
    9. current_page start_page end_page
    10. 1 0 5
    11. 2 5 10
    12. 3 10 15
    13. 4 15 20
    14. 可以很明显的看出规律
    15. start_page = (current_page - 1) * per_page_num
    16. end_page = current_page* per_page_num

    三、数据总页面获取

    • 当我问你下面几个问题的时候,你的内心肯定是鄙视的,不信的话那就请听题
    • 问题1:总数据有100条,每页展示10条,总共需要几页?
      • 答案:10条
    • 问题2:总数据有101条,每页展示10条,总共需要几页?
      • 答案:11条
    • 问题3:如何通过代码算出到底需要多少条?
      • 答案:去你妹的,不会!!!

    四、内置方法之divmod

    1. divmod(100,10)
    2. (10, 0) # 10页
    3. divmod(101,10)
    4. (10, 1) # 11页
    5. divmod(99,10)
    6. (9, 9) # 10页
    7. # 余数只要不是0就需要在第一个数字上加一
    • 我们可以判断元祖的第二个数字是否为0
    • 从而确定到底需要多少页来展示数据
    1. book_queryset = models.Book.objects.all()
    2. all_count = book_queryset.count() # 数据总条数
    3. all_pager, more = divmod(all_count, per_page_num)
    4. if more: # 有余数则总页数加一
    5. all_pager += 1
    • 至此分页器大致的功能及思路我们就已经大致清楚了
    • 最后我们只需要利用start_page和end_page对总数据进行切片取值
      • 再传入前端页面就能够实现分页展示
    1. book_list = models.Book.objects.all()[start_page:end_page]
    2. return render(request,'booklist.html',locals())
    • 接下来就是前端页面的代码编写了
    1. {% for book in book_list %}
    2. {{ book.title }}

    3. {% endfor %}
    • 现在我们实现了最简单的分页
      • 但是前端没有按钮去让用户点击需要看第几页
      • 所以我们需要渲染分页器相关代码
      • 这里我们不做要求直接去bootstrap框架拷贝代码即可

    五、终极大法

    • 上面是自定义分页器开发流程的基本思路
      • 我们不需要掌握代码的编写,
      • 只需要掌握基本用法即可
    • 自定义分页器封装代码
    1. class Pagination(object):
    2. def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
    3. """
    4. 封装分页相关数据
    5. :param current_page: 当前页
    6. :param all_count: 数据库中的数据总条数
    7. :param per_page_num: 每页显示的数据条数
    8. :param pager_count: 最多显示的页码个数
    9. """
    10. try:
    11. current_page = int(current_page)
    12. except Exception as e:
    13. current_page = 1
    14. if current_page < 1:
    15. current_page = 1
    16. self.current_page = current_page
    17. self.all_count = all_count
    18. self.per_page_num = per_page_num
    19. # 总页码
    20. all_pager, tmp = divmod(all_count, per_page_num)
    21. if tmp:
    22. all_pager += 1
    23. self.all_pager = all_pager
    24. self.pager_count = pager_count
    25. self.pager_count_half = int((pager_count - 1) / 2)
    26. @property
    27. def start(self):
    28. return (self.current_page - 1) * self.per_page_num
    29. @property
    30. def end(self):
    31. return self.current_page * self.per_page_num
    32. def page_html(self):
    33. # 如果总页码 < 11个:
    34. if self.all_pager <= self.pager_count:
    35. pager_start = 1
    36. pager_end = self.all_pager + 1
    37. # 总页码 > 11
    38. else:
    39. # 当前页如果<=页面上最多显示11/2个页码
    40. if self.current_page <= self.pager_count_half:
    41. pager_start = 1
    42. pager_end = self.pager_count + 1
    43. # 当前页大于5
    44. else:
    45. # 页码翻到最后
    46. if (self.current_page + self.pager_count_half) > self.all_pager:
    47. pager_end = self.all_pager + 1
    48. pager_start = self.all_pager - self.pager_count + 1
    49. else:
    50. pager_start = self.current_page - self.pager_count_half
    51. pager_end = self.current_page + self.pager_count_half + 1
    52. page_html_list = []
    53. # 添加前面的nav和ul标签
    54. page_html_list.append('''
      • ''')
      • first_page = '
      • 首页
      • ' % (1)
    55. page_html_list.append(first_page)
    56. if self.current_page <= 1:
    57. prev_page = '
    58. 上一页
    59. '
  • else:
  • prev_page = '
  • 上一页
  • ' % (self.current_page - 1,)
  • page_html_list.append(prev_page)
  • for i in range(pager_start, pager_end):
  • if i == self.current_page:
  • temp = '
  • %s
  • ' % (i, i,)
  • else:
  • temp = '
  • %s
  • ' % (i, i,)
  • page_html_list.append(temp)
  • if self.current_page >= self.all_pager:
  • next_page = '
  • 下一页
  • '
  • else:
  • next_page = '
  • 下一页
  • ' % (self.current_page + 1,)
  • page_html_list.append(next_page)
  • last_page = '
  • 尾页
  • ' % (self.all_pager,)
  • page_html_list.append(last_page)
  • # 尾部添加标签
  • page_html_list.append('''
  • ''')
  • return ''.join(page_html_list)
  • 六、自定义分页器使用

    【1】后端

    1. def get_book(request):
    2. book_list = models.Book.objects.all()
    3. current_page = request.GET.get("page",1)
    4. all_count = book_list.count()
    5. page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
    6. page_queryset = book_list[page_obj.start:page_obj.end]
    7. return render(request,'booklist.html',locals())

    【2】前端

    1. <div class="container">
    2. <div class="row">
    3. <div class="col-md-8 col-md-offset-2">
    4. {% for book in page_queryset %}
    5. <p>{{ book.title }}p>
    6. {% endfor %}
    7. {{ page_obj.page_html|safe }}
    8. div>
    9. div>
    10. div>
  • 相关阅读:
    原型对象、实例、原型链的联系
    Golang学习记录:基础篇练习(一)
    智慧机场数字孪生大屏升级智慧出行全方位服务
    【踩坑】PyTorch中指定GPU不生效和GPU编号不一致问题
    math库常用函数+产生随机数总结
    CSS之布局系列--顶部导航栏二级菜单居中展示
    【测试人生】游戏业务测试落地精准测试专项的一些思路
    代理模式详解
    【微信小程序】全局配置
    2024年最新最全最好用的10大开源项目管理软件
  • 原文地址:https://blog.csdn.net/qq_53842456/article/details/134536276