Django扩展 分页组件
我们在展示信息过程中,如果信息量过多,会给人非常的不友好,这个时候需要通过分页使得界面更简洁友好
Django 基于GET请求的分页功能
假设 每一个 显示十条数据 可得到以下公式
| 页码 | 起始 | 结束 |
|---|---|---|
| 1 | 0 | 10 |
| 2 | 10 | 20 |
| 3 | 20 | 30 |
| ... | ... | ... |
| ... | (page-1)*5 | page*10 |
我们用代码实现一下吧
page_num = int(request.GET.get("page")) # 获取页码数 per_page_num = 10 # 每页显示条数 # 通过条件对查询到的数据进行切片处理 customers_obj = models.Customer.objects.all()[ (page_num-1)*per_page_num:page_num*per_page_num ]
我们需要在前端生成分页按钮
分析
- 需要获取每页显示的数量
- 需要获取页码生成的数量
- 前端进行循环生成
页码生成的数量 = 数据总数 / 每页显示的数量
def customers(request): page_num = int(request.GET.get("page")) per_page_num = 10 # 每页显示条数 customers_count = models.Customer.objects.all().count() # 获取总数据数量 shanum, yunum = divmod(customers_count, per_page_num) # 计算商数和余数 # 生成要展示的页码数 if yunum: page_num_count = shanum + 1 else: page_num_count = shanum # 根据每页显示的条数对查出来的数据进行切割 customers_obj = models.Customer.objects.all()[ (page_num-1)*per_page_num:page_num*per_page_num ] return render( request, "saleshtml\\customers.html", { "customers_obj": customers_obj, "page_num_count": range(1, page_num_count+1) # 展示页码没有第一页 } )
<nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> {% for i in page_num_range %} <li><a href="/customers/?page={{i}}">{{i}}</a></li> {% endfor %} <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav>

- 生成页面样式不友好 如果上百页 就一堆页码条
对页码生成逻辑进行改进
| 所在页码 | 字段1 | 字段2 | 字段3 | 字段4 | 字段5 |
|---|---|---|---|---|---|
| 3 | 1 | 2 | 3 | 4 | 5 |
| 4 | 2 | 3 | 4 | 5 | 6 |
| 5 | 3 | 4 | 5 | 6 | 7 |
| 6 | 4 | 5 | 6 | 7 | 8 |
分析
- 字段三两边的数量: 分页按钮的条数 整除 2
- 分页按钮起始: 当前页码 - 字段三两边的数量
- 分页按钮结束: 当前页码 + 字段三两边的数量
def customers(request): try: page_num = int(request.GET.get("page")) except Exception: page_num = 1 per_page_num = 10 # 每页显示条数 customers_count = models.Customer.objects.all().count() # 获取总数据数量 shanum, yunum = divmod(customers_count, per_page_num) # 计算商数和余数 # 生成要展示的页码数 if yunum: page_num_count = shanum + 1 else: page_num_count = shanum # 如果页码数小于等于零 或者大于总页码数 让他不出问题 if page_num <= 0: page_num = 1 elif page_num > page_num_count: page_num = page_num_count # 根据每页显示的条数对查出来的数据进行切割 customers_obj = models.Customer.objects.all()[ (page_num-1)*per_page_num:page_num*per_page_num ] page_num_show = 5 # 分页按钮生成的数量 half_show = page_num_show//2 # 分页按钮中心两端的数量 start_page_num = page_num - half_show # 开始位置 end_page_num = page_num + half_show +1 # 结束位置 page_num_range = range(start_page_num, end_page_num) return render( request, "saleshtml\\customers.html", { "customers_obj": customers_obj, "page_num_range": page_num_range, } )

问题:

解决:
- 页码数由后台生成
start_page_num = page_num - half_show # 开始位置 end_page_num = page_num + half_show +1 # 结束位置
- 解决问题
def customers(request): try: page_num = int(request.GET.get("page")) except Exception: page_num = 1 per_page_num = 10 # 每页显示条数 customers_count = models.Customer.objects.all().count() # 获取总数据数量 shanum, yunum = divmod(customers_count, per_page_num) # 计算商数和余数 # 生成要展示的页码数 if yunum: page_num_count = shanum + 1 else: page_num_count = shanum # 如果页码数小于等于零 或者大于总页码数 让他不出问题 if page_num <= 0: page_num = 1 elif page_num > page_num_count: page_num = page_num_count # 根据每页显示的条数对查出来的数据进行切割 customers_obj = models.Customer.objects.all()[ (page_num-1)*per_page_num:page_num*per_page_num ] page_num_show = 5 # 分页按钮生成的数量 half_show = page_num_show//2 # 分页按钮中心两端的数量 if page_num - half_show <= 0: start_page_num = 1 end_page_num = page_num_show + 1 elif page_num + half_show > page_num_count: start_page_num = page_num_count - page_num_show + 1 end_page_num = page_num_count + 1 else: start_page_num = page_num - half_show # 开始位置 end_page_num = page_num + half_show +1 # 结束位置 page_num_range = range(start_page_num, end_page_num) return render( request, "saleshtml\\customers.html", { "customers_obj": customers_obj, "page_num_range": page_num_range, } )
对分页功能进行封装
封装到后台
def customers(request): try: page_num = int(request.GET.get("page")) except Exception: page_num = 1 per_page_num = 10 # 每页显示条数 customers_count = models.Customer.objects.all().count() # 获取总数据数量 shanum, yunum = divmod(customers_count, per_page_num) # 计算商数和余数 # 生成要展示的页码数 if yunum: page_num_count = shanum + 1 else: page_num_count = shanum # 如果页码数小于等于零 或者大于总页码数 让他不出问题 if page_num <= 0: page_num = 1 elif page_num > page_num_count: page_num = page_num_count # 根据每页显示的条数对查出来的数据进行切割 customers_obj = models.Customer.objects.all()[ (page_num-1)*per_page_num:page_num*per_page_num ] page_num_show = 5 # 分页按钮生成的数量 half_show = page_num_show//2 # 分页按钮中心两端的数量 if page_num - half_show <= 0: start_page_num = 1 end_page_num = page_num_show + 1 elif page_num + half_show > page_num_count: start_page_num = page_num_count - page_num_show + 1 end_page_num = page_num_count + 1 else: start_page_num = page_num - half_show # 开始位置 end_page_num = page_num + half_show +1 # 结束位置 page_num_range = range(start_page_num, end_page_num) page_html = '' # 开头标签样式之类 page_per_html = ''' <nav aria-label="Page navigation"> <ul class="pagination">''' page_html += page_per_html # 上一页 if page_num > 1: per_page = f''' <li><a href="/customers/?page={page_num-1}" aria-label="Previous"> <span aria-hidden="true">«</span></a></li>''' page_html += per_page # 循环添加按钮 for page in page_num_range: page_num_html = f''' <li><a href="/customers/?page={page}">{page}</a></li> ''' page_html += page_num_html # 下一页 if page_num < page_num_count: next_page = f''' <li><a href="/customers/?page={page_num+1}" aria-label="Next"> <span aria-hidden="true">»</span> </a></li> ''' page_html += next_page # 标签样式收尾 page_next_html = '''</ul></nav>''' page_html += page_next_html return render( request, "saleshtml\\customers.html", {"customers_obj": customers_obj, "page_html": page_html,})
<!--前端通过safe使字符串变成可用标签--> {{ page_html|safe }}
将分页功能封装成组件
# mark_safe 将后端生成的字符串标记为HTML 前端直接使用 就不用再 {{xxx|salf}} from django.utils.safestring import mark_safe class MyPageNation(): def __init__(self, page_num, total_count, per_page_num, page_num_show, base_url): self.per_page_num = per_page_num # 每页显示数据条数 self.page_num_show = page_num_show # 分页按钮生成的数量 self.base_url = base_url # 分页组件中的URL self.total_count = total_count # 数据的总量 try: page_num = int(page_num) except Exception: page_num = 1 self.page_num = page_num # 请求的page shanum, yunum = divmod(self.total_count, self.per_page_num) # 计算商数和余数 # 生成要展示的页码数 if yunum: self.page_num_count = shanum + 1 else: self.page_num_count = shanum # 如果页码数小于等于零 或者大于总页码数 让他不出问题 if self.page_num <= 0: self.page_num = 1 elif page_num > self.page_num_count: self.page_num = self.page_num_count half_show = self.page_num_show//2 # 分页按钮中心两端的数量 if page_num - half_show <= 0: start_page_num = 1 end_page_num = self.page_num_show + 1 elif page_num + half_show > self.page_num_count: start_page_num = self.page_num_count - self.page_num_show + 1 end_page_num = self.page_num_count + 1 else: start_page_num = page_num - half_show end_page_num = page_num + half_show + 1 self.start_page_num = start_page_num # 开始位置 self.end_page_num = end_page_num # 结束位置 @property def start_data_num(self): return (self.page_num-1)*self.per_page_num @property def end_data_num(self): return self.page_num*self.per_page_num def page_html(self): page_num_range = range(self.start_page_num, self.end_page_num) page_html = '' # 开头标签样式之类 page_per_html = ''' <nav aria-label="Page navigation"> <ul class="pagination">''' page_html += page_per_html # 上一页 if self.page_num > 1: per_page = f''' <li><a href="{self.base_url}?page={self.page_num-1}" aria-label="Previous"> <span aria-hidden="true">«</span></a></li>''' page_html += per_page # 循环添加按钮 for page in page_num_range: if self.page_num == page: page_num_html = f''' <li class="active"><a href="{self.base_url}?page={page}">{page}</a></li> ''' else: page_num_html = f''' <li><a href="{self.base_url}?page={page}">{page}</a></li> ''' page_html += page_num_html # 下一页 if self.page_num < self.page_num_count: next_page = f''' <li><a href="{self.base_url}?page={self.page_num+1}" aria-label="Next"> <span aria-hidden="true">»</span> </a></li> ''' page_html += next_page # 标签样式收尾 page_next_html = '''</ul></nav>''' page_html += page_next_html return mark_safe(page_html) # 将最后生成的html标签返回给前端


浙公网安备 33010602011771号