分页初版:
一.建项目并生成500条数据的出版社
(1)建一项目:

(2) models.py中:
from django.db import models class Publisher(models.Model): name = models.CharField(max_length=12) addr = models.CharField(max_length=255)
python manage.py makemigrations
python manage.py migrate
(3)piliang.py中:---python中用文件生成批量数据
我想在数据库中创建500条数据/500个出版社?--怎么批量创建
import os if __name__ == '__main__': os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'about_page.settings') import django django.setup() from app01.models import Publisher # 先创建500个Publisher对象 obj_list = (Publisher(name='小三{}'.format(i),addr='小四{}'.format(i)) for i in range(500)) #bulk_create--一次创建完一次提交 Publisher.objects.bulk_create(obj_list)
右键运行piliang.py文件--->data source:sqlite--->测试并下载,最后如下图有表中数据了

(4)urls.py:
from django.contrib import admin from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publisher_list/$', views.publisher_list), ]
(5)views.py:
查找到所有的数据。
from django.shortcuts import render from app01.models import Publisher def publisher_list(request): data = Publisher.objects.all() return render(request,'publisher_list.html',{'publisher_list':data})
(6)publisher_list.html:
.复制bootstrap分页样式。
.从bootcdn中复制3.3.7版本.
.搭一珊格系统.

.写一表格:bootstrap中复制带边框的表格。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"> </head> <body> <div class="container"> <div class="row"> <div class="col-md-12"> <h1>出版社列表</h1> <div class="bs-example" data-example-id="bordered-table"> <table class="table table-bordered table-strip"> <thead> <tr> <th>#</th> <th>男生</th> <th>女生</th> </tr> </thead> <tbody> {% for publisher in publisher_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ publisher.name }}</td> <td>{{ publisher.addr }}</td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </div> </body> </html>
.如下图中修改端口为8010

.启动项目,效果如下图有很多多数据,不方便查看:

二.分页初识
想实现url地址栏中输入?page=1则为第一页,?page=n则为第n页的分页效果。
分页(Python基础) 每页显示10条 每页显示per_page条
当前页码: 切片的起始位置: 第1页 0 - 10 第2 11 - 20 第3页 20 - 30 ... n 10*(n-1) - n * 10 总条: 每页条: 几页: 10 10 1 11 10 2 100 10 10
n m n/m
(1)views.py中:
from django.shortcuts import render from app01.models import Publisher def publisher_list(request): current_page = int(request.GET.get('page',1))#拿到当前页码,如果取不到则返回默认值第1页 per_page = 10 #每页为10条数据 start = 10*(current_page-1) #切片起始位置 end = current_page * per_page #切片结尾位置 data = Publisher.objects.all()[start:end] #从所有数据中切片只取切出的条数数据 return render(request,'publisher_list.html',{'publisher_list':data})
最终效果如下:

从bootstrap中复制分页组件----便于数据查看,直接点击分页即可跳转而不用在url地址栏中输入。
在publisher_list.html中:在tabel表格标签后建一div标签并把分页代码复制在此div标签中即可。效果如下:

三.分页初版
上图效果中点击分页栏还不能实现跳转。且url的?page值只能接收整型,那我想要的是输入的不是整数那默认跳到第1页。且当你访问的页超过最后页的页码那我就默认显示最后一基页。
1.views.py中: url的?page值只能接收整型,那我想要的是输入的不是整数那默认跳到第1页,效果如下图:
from django.shortcuts import render from app01.models import Publisher def publisher_list(request): try: current_page = int(request.GET.get('page',1))#拿到当前页码,如果取不到则返回默认值第1页 except Exception as e: current_page = 1 per_page = 10 #每页为10条数据 start = 10*(current_page-1) #切片起始位置 end = current_page * per_page #切片结尾位置 data = Publisher.objects.all()[start:end] #从所有数据中切片只取切出的条数数据 return render(request,'publisher_list.html',{'publisher_list':data})
url的?page值只能接收整型,那我想要的是输入的不是整数那默认跳到第1页,效果如下图:

2.当你访问的页超过最后页的页码那我就默认显示最后一基页
总共有多少条数据? 每页显示10条数据。总共需要多少页?
views.py中:
from django.shortcuts import render from app01.models import Publisher def publisher_list(request): try: current_page = int(request.GET.get('page',1))#拿到当前页码,如果取不到则返回默认值第1页 except Exception as e: current_page = 1 per_page = 10 #每页为10条数据 query_set = Publisher.objects.all() total_count = query_set.count() #总共多少条数据 #计算需要多少页 total_page, more = divmod(total_count, per_page) #more是余数 if more:#有值 total_page += 1 #总页码数 #如果访问的页码数超过总页码数默认显示最后一页 if current_page > total_page: current_page = total_page start = 10*(current_page-1) #切片起始位置 end = current_page * per_page #切片结尾位置 data = query_set[start:end] #从所有数据中切片只取切出的条数数据 return render(request,'publisher_list.html',{'publisher_list':data})
效果如下:

3.点分页栏的页码时能显示对应页面.
(1)publisher_list.html中分页栏页码都是a标签,所以相当于第二图中访问某页就是?page=*

改成如这样后,在页面点分页栏页码会跳到对应页上了。

但这就有个问题:有500页那要写500个a标签?--所以这里不能写死,写个for循环--但html页面中不能写for i in range循环,所以我在后端生成这段a标签的代码,最后保存在一变量返回给前端
把这段代码拿到后端生成:
<nav aria-label="Page navigation"> <ul class="pagination"> <li><a href="/publisher_list/?page=1">1</a></li> <li><a href="/publisher_list/?page=2">2</a></li> <li><a href="/publisher_list/?page=3">3</a></li> <li><a href="/publisher_list/?page=4">4</a></li> <li><a href="/publisher_list/?page=5">5</a></li> </ul> </nav>
最后publisher_list.html中:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"> </head> <body> <div class="container"> <div class="row"> <div class="col-md-12"> <h1>出版社列表</h1> <div class="bs-example" data-example-id="bordered-table"> <table class="table table-bordered table-strip"> <thead> <tr> <th>#</th> <th>男生</th> <th>女生</th> </tr> </thead> <tbody> {% for publisher in publisher_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ publisher.name }}</td> <td>{{ publisher.addr }}</td> </tr> {% endfor %} </tbody> </table> <div> {{ page_html|safe }} </div> </div> </div> </div> </div> <form action="" method="get"> <input type="number" name="page"> <input type="submit" name="跳转"> </form> </body> </html>
(2)views.py中:
把分页代码一次返回,在后端相当于用字符串拼接成html代码。
高亮显示当前页码。
问题:页码有出现左边有负数和零(越界)和右边越界。
问题:总页码数小于最大要显示的页码数。
添加首页。
添加尾页。
添加上一页。
添加下一页。
跳转框。(publisher_list.html中加一form表单中两input框即可)
from django.shortcuts import render from app01.models import Publisher # Create your views here. def publisher_list(request): query_set = Publisher.objects.all() # 当前页码 try: current_page = int(request.GET.get('page', 1)) except Exception as e: current_page = 1 # 页码必须是大于0的数 if current_page < 1: current_page = 1 # 每一页显示10条数据 per_page = 10 # 问:总共需要多少页 # 1. 总共有多少条数据 total_count = query_set.count() # SQL语句的效率高 # 2. 计算需要多少页 total_page, more = divmod(total_count, per_page) if more: total_page += 1 # 如果访问的页码数超过了总页码数,默认展示最后一页 # if current_page > total_page: # current_page = total_page current_page = total_page if current_page > total_page else current_page # 数据切片的开始位置 start = per_page * (current_page - 1) # 数据切片的结束为止 end = current_page * per_page # 获取当前页面的数据 data = query_set[start:end] # 页面最多显示的页码数 show_page = 9 # 最多显示页码的一半 half_show_page = show_page // 2 # 页面显示页码的开始 # 如果总页码数小于最大要显示的页码数 if total_page < show_page: show_page_start = 1 show_page_end = total_page # 左边越界 elif current_page - half_show_page < 1: show_page_start = 1 show_page_end = show_page # 右边越界 elif current_page + half_show_page > total_page: show_page_end = total_page show_page_start = total_page - show_page + 1 else: show_page_start = current_page - half_show_page # 页面显示页码的结束 show_page_end = current_page + half_show_page # 生成分页的HTML代码 page_list = [] #空列表,把下面的这些放里边 # 添加分页代码的前缀 page_list.append('<nav aria-label="Page navigation"><ul class="pagination">') # 添加首页 page_list.append('<li><a href="/publisher_list/?page=1">首页</a></li>') # 添加上一页 if current_page - 1 <1: # 已经到头啦,不让点上一页啦 page_list.append('<li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">«</span></a></li>') else: page_list.append('<li><a href="/publisher_list/?page={}" aria-label="Previous"><span aria-hidden="true">«</span></a></li>'.format(current_page-1)) for i in range(show_page_start, show_page_end+1): if i == current_page:#当前页码高亮active s = '<li class="active"><a href="/publisher_list/?page={0}">{0}</a></li>'.format(i) else: s = '<li><a href="/publisher_list/?page={0}">{0}</a></li>'.format(i) page_list.append(s) # 添加下一页 if current_page + 1 > total_page:#disabled不让点 page_list.append('<li class="disabled"><a href="#" aria-label="Next"><span aria-hidden="true">»</span></a></li>') else: page_list.append('<li><a href="/publisher_list/?page={}" aria-label="Next"><span aria-hidden="true">»</span></a></li>'.format(current_page+1)) # 添加尾页 page_list.append('<li><a href="/publisher_list/?page={}">尾页</a></li>'.format(total_page)) # 添加分页代码的后缀 page_list.append('</ul></nav>') page_html = ''.join(page_list) #把列表里每一个元素拼成一大的html的字符串---把此字符串传到页面即可 return render(request, 'publisher_list.html', {'publisher_list': data, 'page_html':page_html})
最后效果如下:这样分页器就写完了。

四.封装分页代码和添加url_prefix(a标签的url前缀)
把上述分页器代码单独写到一个类里(封装),这样就可以套用在任何项目中,直接使用分页器效果。
在项目下新建一个utils包,
(1)新建utils/mypage.py:
""" 自定义分页组件 可以返回分页的数据和分页的HTML代码 """ from django.http import QueryDict class Pagination(object): def __init__(self, current_page, total_count, url_prefix, query_dict=QueryDict(mutable=True), per_page=10, show_page=9): """ 初始化分分页器,把以下这些值数据封装到此对象中--即这些值需要你调用时在视图函数中要传给分页器 :param url_prefix: a标签的URL前缀 :param query_dict: 空的QueryDict()对象,并且是可修改的 :param current_page: 当前页码数 :param total_count: 数据总数 :param per_page: 每一页显示多少数据, 默认值是10 :param show_page: 页面显示的页码数, 默认值是9 """ # 0.分页的URL前缀 self.url_prefix = url_prefix #a标签的url前缀 self.query_dict = query_dict # 1. 每一页显示10条数据 assert per_page > 0 # 每页显示多少的数据必须是一个大于0的数 self.per_page = per_page # 2. 计算需要多少页 total_page, more = divmod(total_count, per_page) if more: total_page += 1 self.total_page = total_page # 3. 当前页码 try: current_page = int(current_page) except Exception as e: current_page = 1 current_page = total_page if current_page > total_page else current_page # 页码必须是大于0的数 if current_page < 1: current_page = 1 self.current_page = current_page # 4. 页面最多显示的页码数 self.show_page = show_page # 5. 最多显示页码的一半 self.half_show_page = self.show_page // 2 @property def start(self): # 数据切片的开始位置 return self.per_page * (self.current_page - 1) @property def end(self): # 数据切片的结束为止 return self.current_page * self.per_page # 定义一个返回HTML代码的方法 def page_html(self): if self.total_page == 0: return '' # 如果总页码数小于最大要显示的页码数 if self.total_page < self.show_page: show_page_start = 1 show_page_end = self.total_page # 左边越界 elif self.current_page - self.half_show_page < 1: show_page_start = 1 show_page_end = self.show_page # 右边越界 elif self.current_page + self.half_show_page > self.total_page: show_page_end = self.total_page show_page_start = self.total_page - self.show_page + 1 else: show_page_start = self.current_page - self.half_show_page # 页面显示页码的结束 show_page_end = self.current_page + self.half_show_page # 生成分页的HTML代码 page_list = [] # 添加分页代码的前缀 page_list.append('<nav aria-label="Page navigation"><ul class="pagination">') # 添加首页 self.query_dict['page'] = 1 page_list.append('<li><a href="{}?{}">首页</a></li>'.format(self.url_prefix, self.query_dict.urlencode())) # 添加上一 if self.current_page - 1 < 1: # 已经到头啦,不让点上一页啦 page_list.append( '<li class="disabled"><a href="" aria-label="Previous"><span aria-hidden="true">«</span></a></li>') else: self.query_dict['page'] = self.current_page - 1 page_list.append( '<li><a href="{}?{}" aria-label="Previous"><span aria-hidden="true">«</span></a></li>'.format( self.url_prefix, self.query_dict.urlencode()) ) for i in range(show_page_start, show_page_end + 1): self.query_dict['page'] = i if i == self.current_page: s = '<li class="active"><a href="{1}?{2}">{0}</a></li>'.format(i, self.url_prefix, self.query_dict.urlencode()) else: s = '<li><a href="{1}?{2}">{0}</a></li>'.format(i, self.url_prefix, self.query_dict.urlencode()) page_list.append(s) # 添加下一页 if self.current_page + 1 > self.total_page: page_list.append( '<li class="disabled"><a href="" aria-label="Next"><span aria-hidden="true">»</span></a></li>') else: self.query_dict['page'] = self.current_page + 1 page_list.append( '<li><a href="{}?{}" aria-label="Next"><span aria-hidden="true">»</span></a></li>'.format( self.url_prefix, self.query_dict.urlencode()) ) # 添加尾页 self.query_dict['page'] = self.total_page page_list.append('<li><a href="{}?{}">尾页</a></li>'.format(self.url_prefix, self.query_dict.urlencode())) # 添加分页代码的后缀 page_list.append('</ul></nav>') page_html = ''.join(page_list) return page_html
(2)views.py中:使用分页器
from django.shortcuts import render from app01.models import Publisher from utils.mypage import Pagination #导入自定的分页器模块 # Create your views here. def publisher_list(request): url_prefix = request.path_info #拿到当前页的url前缀 current_page = request.GET.get('page', 1) query_set = Publisher.objects.all() total_count = query_set.count() # SQL语句的效率高 # 生成一个分页实例 page_obj = Pagination(current_page, query_set.count(), url_prefix,show_page=5) # 取到当前页面的数据 data = query_set[page_obj.start:page_obj.end] # 取到分页的HTML代码 page_html = page_obj.page_html() return render(request, 'publisher_list.html', {'publisher_list': data, 'page_html':page_html})
(3)在别的项目中如何调用我封装的这个分页器:
如在我的crm项目中导入分页器使用在客户列表页面:
a.把mypage.py拷贝到crm项目下的utils包中:
b.项目视图函数中导入分页器:from utils.mypage import Pagination
c.在views.py中的客户列表页面customer_list方法中作处理:
from utils.mypage import Pagination @login_required() def customer_list(request): url_prefix = request.path_info #获取当前url前缀 current_page = request.GET.get('page', 1) #获取当前页码 query_set = Customer.objects.all()#拿到所有客户及信息 page_obj = Pagination(current_page, query_set.count(), url_prefix, per_page=2)#页码,数据量,url前缀,每页几条--给分页器传这几个值即可 data = query_set[page_obj.start:page_obj.end]#切片 # 2. 在页面上展出出来 return render(request, 'customer_list.html', {'customer_list': data, 'page_html': page_obj.page_html()})#把分页的html字符串代码传给前端
d.在customer_list.html模版中加分页器如下:

这样重新启动我的crm后,就有分页的效果了如下图:

3
4
浙公网安备 33010602011771号