一.思路简介:css
分页是取部分数据到前端显示,显然前端须要2样东西:
1.当前页和显示页面区间
<1>当前页的获取
能够采用get或post的方法,传递个参数,默认为显示首页
我这里用get传送一个p参数,默认p=1(默认p可能没有传真,因此要判断为空时p=1)
<2>页面区间的获取
首先要知道有多少页,而后推算起始页,结束页,由此再推得上一页和下一页,这些均可以由总数据推算得来,因此要传入总数据进行推算,可是这样有个问题:
若是数据不少,那么传入总数据显然不现实,认真思考则会发现其实咱们这里只须要总数据的数量,再进行推算便可,因此相关参数以下:
总页数:总的数据量/每页显示的数量 (不能整除则+1)
(显然咱们还要传入每页显示的数量,或者设置个默认值)html
起始页:起始页要分三种状况,咱们假设页面为70页,一次拿出7页摆放(这里我姑且叫显示页面),当前页在中间,那么数据相似:1-7,2-8...64-70,那么:
当前页为[1,3]时,起始页为1
当前页为[68,70],起始页为64
其余状况,起始页与当前页的间距是相等的,即为显示页面的一半,因此可得:
当前页<显示页面的/2时,起始页=1
最大页-当前页<显示页面的/2时,起始页=最大页-显示页面+1(用70-7+1=64推)
其余状况:起始页=当前页-显示页面/2+1前端
结束页:结束页可由起始页推得,由于整个显示区间是固定的
结束页=起始页+显示页面-1
上一页和下一页只要注意下极值便可,即等于首页和尾页就不该该再有值了python
2.数据
数据的获取是基于页面的分割,因此在页面分割中顺便作数据的区间取值
数据起始位置:(当前页-1)x 每页显示的条目数
数据结束位置:当前页 x每页显示的条目数django
前端须要这么多数据,可是他们共同点都是页面分割而来,因此实现就是把页面分割做为一个类对象,再传递给前端bootstrap
2、代码 pager.py `` class Pagination(object): def __init__(self, dataCount, currentPage=1, cowCount=10, perPageCount=10): self.totalCount = dataCount self.perPageCount=perPageCount self.cowCount=cowCount if currentPage <= 0: self.currentPage=1 elif currentPage>self.max_page: self.currentPage=self.max_page else: self.currentPage=currentPage @property def max_page(self): a,b=divmod(self.totalCount,self.perPageCount) if b==0: return a else: return a+1 @property def start_page(self): # 1-10 2-11 3-12 # 1-7 2-8 3-9 # 假设当前页在中间,则有: step=int(self.cowCount/2) if self.currentPage<=step: return 1 elif self.max_page-self.currentPage<step: return self.max_page-self.cowCount+1 else: return self.currentPage-step+1 @property def end_page(self): return self.start_page+self.cowCount-1 @property # 模板语言的循环语句只有for in结构,只能返回列表供模板页面使用 def page_range(self): return range(self.start_page, self.end_page+1) @property def next_page(self): if self.currentPage<self.max_page: return self.currentPage+1 else: return "out" @property def prev_page(self): if self.currentPage > 1: return self.currentPage-1 else: return "out" def data_start(self): return (self.currentPage-1)*self.perPageCount def data_end(self): return self.currentPage * self.perPageCount
view部分:app
from cdnpanel.pager import Pagination def test(request): dataCount=Domain.objects.filter(User__username="linzb").count() page_v=request.GET.get("p") if page_v : currentPage = int(page_v) else: currentPage = 0 page_obj=Pagination(dataCount,currentPage,8) data_start=page_obj.data_start() data_end=page_obj.data_end() # data_obj=Domain.objects.filter(id__gte=98,id__lte=105) data_obj=Domain.objects.all()[data_start:data_end] print(page_obj.start_page,page_obj.end_page) return render(request, 'test.html',{"data":data_obj,"page_obj":page_obj,"url":"test"})
test.html部分dom
{% load static %} <link rel="stylesheet" href="{% static 'plugin/bootstrap/css/bootstrap.min.css' %}"> <link href="//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> <tbody> {% for item in data %} <tr data_id="{{ item.id }}"> <p> <td>{{ item.domain }}</td></p> <p><td>{{ item.src }}</td></p> </tr> {% endfor %} </tbody> {% if page_obj.prev_page == "out" %} <a href="#">上一页</a> {% else %} <a href="/{{ url }}?p={{ page_obj.prev_page }}" class="btn">上一页</a> {% endif %} {% for a_ele in page_obj.page_range %} {% if a_ele == page_obj.currentPage %} <a href="/{{url }}?p={{ a_ele }}" class="btn btn-default btn-xs" style="size:30px;font-size:30px;color: red">{{ a_ele }}</a> {% else %} <a href="/{{url }}?p={{ a_ele }}" class="btn" >{{ a_ele }}</a> {% endif %} {% endfor %} {% if page_obj.next_page == "out" %} <a href="#" class="btn">下一页</a> {% else %} <a href="/{{ url }}?p={{ page_obj.next_page }}" class="btn">下一页</a> {% endif %} {{ page_obj.currentPage }}/{{ page_obj.max_page }}
把前端分页部分独立出来(之后能够作通用模板)
pager.htmlide
{% if page_obj.prev_page == "out" %} <a href="#">上一页</a> {% else %} <a href="/{{ url }}?p={{ page_obj.prev_page }}" class="btn">上一页</a> {% endif %} {% for a_ele in page_obj.page_range %} {% if a_ele == page_obj.currentPage %} <a href="/{{url }}?p={{ a_ele }}" class="btn btn-default btn-xs" style="size:30px;font-size:30px;color: red">{{ a_ele }}</a> {% else %} <a href="/{{url }}?p={{ a_ele }}" class="btn" >{{ a_ele }}</a> {% endif %} {% endfor %} {% if page_obj.next_page == "out" %} <a href="#" class="btn">下一页</a> {% else %} <a href="/{{ url }}?p={{ page_obj.next_page }}" class="btn">下一页</a> {% endif %} {{ page_obj.currentPage }}/{{ page_obj.max_page }}
在上一篇中进行应用:
把view中index部分的代码改成函数
def index(request): if request.COOKIES.get("is_login"): # username = request.COOKIES.get('username') # data = Domain.objects.filter(User__username=username) # engine = Proxy.objects.all() # user = User.objects.all() # return render(request, 'index.html', {'data': data, "engine": engine, "user": user}) username = request.COOKIES.get('username') dataCount = Domain.objects.filter(User__username=username).count() page_v = request.GET.get("p") if page_v: currentPage = int(page_v) else: currentPage = 0 page_obj = Pagination(dataCount, currentPage, 7) data_start = page_obj.data_start() data_end = page_obj.data_end() data_obj = Domain.objects.all()[data_start:data_end] engine = Proxy.objects.all() user = User.objects.all() return render(request, 'index.html', {'data': data_obj, "engine": engine, "user": user,"page_obj":page_obj,"url":"index"}) else: return redirect('/login')
在index.html中引用:
{% include 'pager.html' %} 在原来的代码中加入此句
效果图:
debug:
1.python manage.py migrate报错 django.db.utils.OperationalError: (1829, "Cannot drop column 'id': needed in a foreign key constraint 'cdnpanel_domain_m_domain_id_63a1eb5a_fk_cdnpanel_domain_id' of table 'cdnpanel_domain_m'") 缘由:django 建立外键也会为其建立索引,当被约束的表结构出现变动便会报错 解决:删除对应外键索引便可 语法: alter table TB drop foreign key INDEX_NAME; 2.django从新生成表报错找不到错误缘由(如有数据先备份) 可尝试:<1>rm -rf migrations/__pycache__/ <2>delete from django_migrations where app=‘要删的app名’; 实在不行: 删掉migrations下除了__init__.py之外全部文件(结合<1><2>) 3. return range(self.start_page, self.end_page) TypeError: 'float' object cannot be interpreted as an integer 缘由:函数返回值中self.perPageCount/2可能为小数 解决:return self.currentPage-int(self.perPageCount/2) 分页理论上要拿数据(一次拿总数据,一次数据分割),可是为了减小数据读取操做,传入最大条目数,返回取值区间取值(区间取数据,代价更小)