Django实战项目-学习任务系统-查询列表分页显示
接着上期代码框架,6个主要功能基本实现,剩下的就是细节点的完善优化了。
接着优化查询列表分页显示功能,有很多菜单功能都有查询列表显示页面情况,如果数据量多,不分页显示的话,页面展示效果就不太好。
本次增加查询列表分页显示功能,对一个查询列表功能进行分页改造,其他依此类推即可。
第一步:Django的分页器(paginator)简介
Django的分页器(paginator)是一个内置的分页组件,它可以方便地实现分页功能。当页面需要显示大量数据时,例如超过10000条,使用分页器可以提高阅读体验并减轻服务器压力。
要使用Django的分页器,首先需要从`django.core.paginator`模块中引入`Paginator`类以及相关的异常模块:`PageNotAnInteger`和`EmptyPage`。
`Paginator`是用于管理整个分页的逻辑,如控制总共有多少页、页码区间等。而`Page`类则是用来管理当前这个页面的一些属性。
以下是创建`Paginator`对象的简单语法:
```python
class Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True)
```
其中,`object_list`是你要分页的数据列表,`per_page`是每页显示的数据条数。
例如:
给 Paginator 一个对象列表,以及你希望在每个页面上拥有的项目数,它提供了访问每页项目的方法:
>>> from django.core.paginator import Paginator >>> objects = ['john', 'paul', 'george', 'ringo'] >>> p = Paginator(objects, 2) >>> p.count 4 >>> p.num_pages 2 >>> type(p.page_range) <class 'range_iterator'> >>> p.page_range range(1, 3) >>> page1 = p.page(1) >>> page1 <Page 1 of 2> >>> page1.object_list ['john', 'paul'] >>> page2 = p.page(2) >>> page2.object_list ['george', 'ringo'] >>> page2.has_next() False >>> page2.has_previous() True >>> page2.has_other_pages() True >>> page2.next_page_number() Traceback (most recent call last): ... EmptyPage: That page contains no results >>> page2.previous_page_number() 1 >>> page2.start_index() # The 1-based index of the first item on this page 3 >>> page2.end_index() # The 1-based index of the last item on this page 4 >>> p.page(0) Traceback (most recent call last): ... EmptyPage: That page number is less than 1 >>> p.page(3) Traceback (most recent call last): ... EmptyPage: That page contains no results
第二步:修改视图文件
./mysite/study_system/views.py
def getStudyPointsList(request): ''' @方法名称: 获取积分明细列表 @作 者: PandaCode辉 @weixin公众号: PandaCode辉 @创建时间: 2023-10-10 ''' # 响应容器 rsp_dict = {} # 获取当前用户名 username = request.session.get('username') # 根据用户名获取用户对象 cur_user = StudyUser.objects.get(username=username) print('根据用户名查询用户对象:' + str(cur_user)) # 2. 获取要分页的数据集合(例如从数据库查询),当前用户的全部积分明细, .order_by('-created_time') 降序排列 data_list = StudyPoint.objects.filter(user_id=cur_user).order_by('-created_time') # 3. 每页显示的数据数量 items_per_page = 5 # 4. 创建 Paginator 对象 paginator = Paginator(data_list, items_per_page) # 5. 获取当前页数(从请求参数中获取,或者默认为第一页) current_page_num = request.GET.get('page', 1) ''' 1.整个数据表 paginator.count 数据总数 paginator.num_pages 总页数 paginator.page_range 页码的列表 2.当前页 curuent_page.has_next() 是否有下一页 curuent_page.next_page_number() 下一页的页码 curuent_page.has_previous() 是否有上一页 curuent_page.previous_page_number() 上一页的页码 ''' # 6. 获取当前页的数据对象 try: current_page_data = paginator.page(current_page_num) except EmptyPage: # 处理页码超出范围的情况 current_page_data = paginator.page(paginator.num_pages) # 获取整个表的总页数 total_page = paginator.num_pages pag_range = [] if total_page <= 11: # 判断当前页是否小于11个 pag_range = paginator.page_range elif total_page > 11: if current_page_num < 6: pag_range = range(1, 11) elif current_page_num > paginator.num_pages - 5: pag_range = range(total_page - 9, total_page + 1) else: pag_range = range(current_page_num - 5, current_page_num + 5) # 当前页+5大于最大页数时 # 7. 在模板中使用 current_data_page 来渲染分页数据 # 查询待完成任务列表 rsp_dict['data_list'] = data_list rsp_dict['paginator'] = paginator rsp_dict['current_page_num'] = current_page_num rsp_dict['current_page_data'] = current_page_data rsp_dict['pag_range'] = pag_range context_object_name = "study_points_list" template_name = "study_system/home.html" # 'html_file': 'xxx.html' 动态指定模板页面 ; 'menuTo': 'task' = 任务管理 ; rsp_dict['html_file'] = 'study_system/item/studyPointsList.html' rsp_dict['context_object_name'] = context_object_name return render(request, template_name, rsp_dict)
第三步:修改页面模板代码
1. 积分流水列表页面
./mysite/study_system/templates/study_system/item/studyPointsList.html
<style type="text/css"> table tr td { font-size: 1.5em; } </style> <!-- 结果显示区 --> <div align="center"> <table style='width: 100%;'> <tr> <td colspan="6" align="center">积分明细流水</td> </tr> <tr style="font-weight: bold; background: #FFEC8B;text-align: center"> <td>序号</td> <td>积分说明</td> <td>交易类型</td> <td>积分数</td> <td>交易时间</td> <td>用户名</td> </tr> {% if current_page_data %} {% for studyPoints in current_page_data %} {% if studyPoints.point_type == 0 %} <tr style="color: blue;text-align: center"> {# forloop.counter 可以记录循环的次数,作为列表序号#} <td>{{ forloop.counter }}</td> <td>{{ studyPoints.point_name }}</td> <td>兑换物品</td> <td>{{ studyPoints.points_nums }}</td> <td>{{ studyPoints.created_time|date:'Y-m-d H:i:s' }}</td> <td>{{ studyPoints.user_id.username }}</td> </tr> {% elif studyPoints.point_type == 1 %} <tr style="color: red;text-align: center"> <td>{{ forloop.counter }}</td> <td>{{ studyPoints.point_name }}</td> <td>成功奖励</td> <td>{{ studyPoints.points_nums }}</td> <td>{{ studyPoints.created_time|date:'Y-m-d H:i:s' }}</td> <td>{{ studyPoints.user_id.username }}</td> </tr> {% elif studyPoints.point_type == 2 %} <tr style="color: green;text-align: center"> <td>{{ forloop.counter }}</td> <td>{{ studyPoints.point_name }}</td> <td>失败处罚</td> <td>{{ studyPoints.points_nums }}</td> <td>{{ studyPoints.created_time|date:'Y-m-d H:i:s' }}</td> <td>{{ studyPoints.user_id.username }}</td> </tr> {% endif %} {% endfor %} {% else %} <tr> <td colspan="6" id="con_title">查无记录</td> </tr> {% endif %} </table> </div> <div align="center"> {% include "study_system/common/page.html" %} </div>
2. 公共页码页面
./mysite/study_system/templates/study_system/common/page.html
<div> <nav aria-label="Page navigation"> <ul class="pagination"> {% if not current_page_data.has_previous %}<!--判断是否有上一页--> <li class="disable"> <a href="#" aria-label="Previous"> <span aria-hidden="true">上一页</span> </a> </li> {% else %} <li> <a href="?page={{ current_page_data.previous_page_number }}" aria-label="Previous"> <span aria-hidden="true">上一页</span> </a> </li> {% endif %} {% for page_range in pag_range %} {% if current_page_num == page_range %}<!--判断遍历的页数是否为当前页,是就添加.avtive 背景色变蓝--> <li class="active"><a href="?page={{ page_range }}">{{ page_range }}</a></li> {% else %} <li><a href="?page={{ page_range }}">{{ page_range }}</a></li> {% endif %} {% endfor %} {% if not current_page_data.has_next %}<!-- 判断是否最后一页 --> <li class="disable"> <a href="?page={{ current_page_num }}" aria-label="Next"> <span aria-hidden="true">下一页</span> </a> </li> {% else %} <li> <a href="?page={{ current_page_data.next_page_number }}" aria-label="Next"> <span aria-hidden="true">下一页</span> </a> </li> {% endif %} </ul> </nav> </div>
第四步:运行测试
1. 点击查看积分流水列表页面
-------------------------------------------------end -------------------------------------------------