Django分页
分页的目的是:在数据量太大分批获取数据并在页面上进行展示
简单的操作就是通过切片获取
1 2
| user_list = models.UserInfo.objects.all()[1:10] user_list = models.UserInfo.objects.all()[10:20]
|
Django自带分页
适合做上下页,只能在Django中用
分页操作实现
首先导入对象Paginator
from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage
在浏览器中通过GET发送当前的页码,后面加上?page=1
如http://127.0.0.1:8000/index.html?page=1
python后台代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| def index(request): """ Djangon内置的分页,实现的功能是上下页 :param request: :return: """ current_page = request.GET.get('page') user_list = models.UserInfo.objects.all() paginator = Paginator(user_list, 10) posts = paginator.page(current_page) return render(request, 'index.html', {'posts': posts})
|
前端代码,通过posts拿到分页后的数据,上下页之前先判断是否有上一页或者下一页,之后拼接路径。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <h1>django内置的分页</h1> <ul> {% for row in posts.object_list %} {# object_list是分页之后的数据列表 #} <li>{{ row.name }}</li> {% endfor %} </ul> <div> {% if posts.has_previous %} <a href="/index.html?page={{ posts.previous_page_number }}">上一页</a> {% endif %} {% if posts.has_next %} {# 判断有下一页的时候 #} <a href="/index.html?page={{ posts.next_page_number }}">下一页</a> {% endif %} </div>
|
关于URL中的问题
在URL中只能接收的是int型的数字,如果传入的是字母,会报错PageNotAnInteger at /index.html,在后台进行异常处理,捕捉异常之后的操作是返回到第一页。
在URL中传入的是负数的话,报错EmptyPage at /index.html,处理同样是返回到第一页
已经在前面导入了异常处理的
from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage
1 2 3 4 5 6 7 8
| try: posts = paginator.page(current_page) except Exception as e: posts = paginator.page(1)
|
Django的页码
Django的页码在数据量很大的时候,会显示所有的分页的页码,比如有300条数据,每页显示10条数据,就会有30个页码。所以需要进行自己开发
在index的上下页中间添加,post下有paginator方法,paginator下有page_range 方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div> {% if posts.has_previous %} <a href="/index.html?page={{ posts.previous_page_number }}">上一页</a> {% endif %} {% for num in posts.paginator.page_range %} {# post下有paginator,paginator下有page_range #} <a href="/index.html?page={{ num }}">{{ num }}</a> {% endfor %} {% if posts.has_next %} {# 判断有下一页的时候 #} <a href="/index.html?page={{ posts.next_page_number }}">下一页</a> {% endif %} </div>
|
总结:
Django的分页适用于上下翻页的情况,不适合中间的页码,如果数据量太大,不适合
自定义分页
可以在任何地方使用,以后封装成一个类
最原始的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| def custom(request): current_page = request.GET.get('page') current_page = int(current_page) per_page = 10 start = (current_page - 1) * per_page end = current_page * per_page user_list = models.UserInfo.objects.all()[start:end] return render(request, 'custom.html', {"user_list": user_list})
|
把页码的计算封装成类
注意类中的参数传值的时候要一一对应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| class PageInfo(object): def __init__(self, current_page, all_count, per_page, ): try: self.current_page = int(current_page) except Exception as e: current_page = 1 self.per_page = per_page a, b = divmod(all_count, per_page) if b: a += 1 self.all_page = a def start(self): return (self.current_page - 1) * self.per_page def end(self): return self.current_page * self.per_page def pager(self): page_list = [] for i in range(1, self.all_page + 1): if i == self.current_page: temp = "<a style='display: inline-block;padding: 5px;margin: 5px;background-color: red' href='/custom.html?page=%s'>%s</a>" % ( i, i) else: temp = "<a style='display: inline-block;padding: 5px;margin: 5px' href='/custom.html?page=%s'>%s</a>" % ( i, i) page_list.append(temp) return ''.join(page_list) def custom(request): all_count = models.UserInfo.objects.all().count() page_info = PageInfo(request.GET.get('page'), all_count, 10) user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()] return render(request, 'custom.html', {"user_list": user_list, 'page_info': page_info})
|
继续优化成页码的显示方式
这种是定义了固定的显示页面数11(当前页和前后5页),现在的问题是两端的极限值的问题
左边必须是当前页>=6
右边的问题是会查不到数据后还显示页码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| class PageInfo(object): def __init__(self, current_page, all_count, per_page, show_page=11): try: self.current_page = int(current_page) except Exception as e: current_page = 1 self.per_page = per_page a, b = divmod(all_count, per_page) if b: a += 1 self.all_page = a self.show_page = show_page def start(self): return (self.current_page - 1) * self.per_page def end(self): return self.current_page * self.per_page def pager(self): half = int((self.show_page-1)/2) begin = self.current_page - half stop =self.current_page +half +1 page_list = [] for i in range(begin,stop): if i == self.current_page: temp = "<a style='display: inline-block;padding: 5px;margin: 5px;background-color: red' href='/custom.html?page=%s'>%s</a>" % ( i, i) else: temp = "<a style='display: inline-block;padding: 5px;margin: 5px' href='/custom.html?page=%s'>%s</a>" % ( i, i) page_list.append(temp) return ''.join(page_list)
|
优化右边的极限
把页面制作成一个插件
放到utils文件夹中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| class PageInfo(object): def __init__(self, current_page, all_count, per_page, base_url, show_page=11): """ :param current_page: :param all_count: 数据库总行数 :param per_page: 每页显示函数 :return: """ try: self.current_page = int(current_page) except Exception as e: self.current_page = 1 self.per_page = per_page a, b = divmod(all_count, per_page) if b: a = a + 1 self.all_pager = a self.show_page = show_page self.base_url = base_url def start(self): return (self.current_page-1) * self.per_page def end(self): return self.current_page * self.per_page def pager(self): page_list = [] half = int((self.show_page-1)/2) if self.all_pager < self.show_page: begin = 1 stop = self.all_pager + 1 else: if self.current_page <= half: begin = 1 stop = self.show_page + 1 else: if self.current_page + half > self.all_pager: begin = self.all_pager - self.show_page + 1 stop = self.all_pager + 1 else: begin = self.current_page - half stop = self.current_page + half + 1 if self.current_page <= 1: prev = "<li><a href='#'>上一页</a></li>" else: prev = "<li><a href='%s?page=%s'>上一页</a></li>" % ( self.base_url, self.current_page-1,) page_list.append(prev) for i in range(begin, stop): if i == self.current_page: temp = "<li class='active'><a href='%s?page=%s'>%s</a></li>" % ( self.base_url, i, i,) else: temp = "<li><a href='%s?page=%s'>%s</a></li>" % ( self.base_url, i, i,) page_list.append(temp) if self.current_page >= self.all_pager: nex = "<li><a href='#'>下一页</a></li>" else: nex = "<li><a href='%s?page=%s'>下一页</a></li>" % ( self.base_url, self.current_page+1,) page_list.append(nex) return ''.join(page_list)
|
使用
1 2 3 4 5 6 7 8 9 10 11 12
| from utils.pager import PageInfo def custom(request): all_count = models.UserInfo.objects.all().count() page_info = PageInfo(request.GET.get( 'page'), all_count, 10, '/custom.html', 11) user_list = models.UserInfo.objects.all( )[page_info.start():page_info.end()] return render(request, 'custom.html', {'user_list': user_list, 'page_info': page_info})
|
前端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" /> </head> <body> <h1>用户列表</h1> <ul> {% for row in user_list %} <li>{{ row.name }}</li> {% endfor %} </ul> <nav aria-label="Page navigation"> <ul class="pagination"> {{ page_info.pager|safe }} </ul> </nav> </body> </html>
|