python后端实现自定义分页功能
目的&环境准备
目的把分页写成一个模块的方式然后在需要分页的地方直接调用模块就行了。
环境准备Django中生成一个APP并且注册,配置URL&Views
- 配置URL
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^user_list/',views.user_list),
]
- 注册APP
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',
]
- 配置models
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class UserList(models.Model):
username = models.CharField(max_length=32)
age = models.IntegerField()
逐步完善分页代码
首先咱们先创建500条数据(之前不要忘记生成数据库)
- 配置views创建数据
#/usr/bin/env python
#-*- coding:utf-8 -*-
from django.shortcuts import render
from django.shortcuts import HttpResponse
import models
# Create your views here.
def user_list(request):
for i in range(500):
dic = {'username': 'name_%d' % i, 'age': i}
models.UserList.objects.create(**dic)
return HttpResponse('OK')
- 配置html显示数据并通过views获取数据显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
{% for line in result %}
<tr>
<td>{{ line.username }}</td>
<td>{{ line.age }}</td>
</tr>
{% endfor %}
</table>
<div>
{{ pager_str|safe }}
</div>
</body>
</html>
- views
def user_list(request):
result = models.UserList.objects.all()
return render(request,'user_list.html',{'result':result})
- 指定显示区间并查询数据,展示煤业显示多少条内容
def user_list(request):
# 获取前端传入的页码
current_page = request.GET.get('page',1)
current_page = int(current_page)
# 动态定义开始范围
start = (current_page-1)*10
# 动态设置结束范围
end = current_page * 10
# 查询指定区间的数据
result = models.UserList.objects.all()[start:end]
return render(request,'user_list.html',{'result':result})
分页代码
- 封装数据
我们通过把上面的代码整理一下整理到函数或类里下次使用的时候直接调用类或者函数即可。
#/usr/bin/env python
#-*- coding:utf-8 -*-
from django.shortcuts import render
from django.shortcuts import HttpResponse
import models
# Create your views here.
class Pager(object):
def __init__(self,current_page):
self.current_page = int(current_page)
#把方法伪造成属性(1)
@property
def start(self):
return (self.current_page-1)*10
@property
def end(self):
return self.current_page*10
def user_list(request):
current_page = request.GET.get('page',1)
page_obj = Pager(current_page)
#把方法改造成属性(2),这样在下面调用方法的时候就不需要加括号了
result = models.UserList.objects.all()[page_obj.start:page_obj.end]
return render(request,'user_list.html',{'result':result})
生成前端按钮
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
{% for line in result %}
<tr>
<td>{{ line.username }}</td>
<td>{{ line.age }}</td>
</tr>
{% endfor %}
</table>
<div>
<a href="/user_list/?page=1">1</a>
<a href="/user_list/?page=2">2</a>
<a href="/user_list/?page=3">3</a>
<a href="/user_list/?page=4">4</a>
<a href="/user_list/?page=5">5</a>
</div>
</body>
</html>
- 通过divmod计算共需要多少页
可以通过divmod(500,10),他会的到一个元组,第一个值是值,第二个值是余数,我们就通过判断他是否有余数来判断是否是整页,如果有余数在整页基础加1即可!
#/usr/bin/env python
#-*- coding:utf-8 -*-
from django.shortcuts import render
from django.shortcuts import HttpResponse
import models
# Create your views here.
class Pager(object):
def __init__(self,current_page):
self.current_page = int(current_page)
#把方法伪造成属性(1)
@property
def start(self):
return (self.current_page-1)*10
@property
def end(self):
return self.current_page*10
def user_list(request):
current_page = request.GET.get('page',1)
page_obj = Pager(current_page)
#吧方法未造成属性(2),这样在下面调用方法的时候就不需要加括号了
result = models.UserList.objects.all()[page_obj.start:page_obj.end]
all_item = models.UserList.objects.all().count()
all_page,div = divmod(all_item,10)
if div > 0:
all_page +=1
pager_str = ""
for i in range(1,all_page+1):
#每次循环生成一个标签
temp = '<a href="/user_list/?page=%d">%d</a>' %(i,i,)
#把标签拼接然后返回给前端
pager_str += temp
return render(request,'user_list.html',{'result':result,'pager_str':pager_str})
- 前端配置
- 存在XSS攻击,为了预防XSS攻击只需要在渲染模板中加入safe 即可!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
{% for line in result %}
<tr>
<td>{{ line.username }}</td>
<td>{{ line.age }}</td>
</tr>
{% endfor %}
</table>
<div>
{{ pager_str|safe }}
</div>
</body>
</html>
- 前端把所有页码渲染出来,有点页码冗余,在后端设置传入的页码的区间,只显示部分页码即可!
当用户点击第6页的时候,这个6永远在中间!所以我们也要让页码动态起来!
#/usr/bin/env python
#-*- coding:utf-8 -*-
from django.shortcuts import render
from django.shortcuts import HttpResponse
import models
# Create your views here.
class Pager(object):
def __init__(self,current_page):
self.current_page = int(current_page)
#把方法伪造成属性(1)
@property
def start(self):
return (self.current_page-1)*10
@property
def end(self):
return self.current_page*10
def page_str(self,all_item,base_url):
all_page, div = divmod(all_item, 10)
if div > 0:
all_page += 1
pager_str = ""
#默认可以看到的页码11个
start = self.current_page - 5
end = self.current_page + 6
#把页面动态起来传入起始和结束
for i in range(start, end):
#判断是否为当前页
if i == self.current_page:
temp = '<a style="color:red;font-size:26px;padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)
else:
temp = '<a style="padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)
# 把标签拼接然后返回给前端
pager_str += temp
return pager_str
def user_list(request):
current_page = request.GET.get('page',1)
page_obj = Pager(current_page)
#吧方法未造成属性(2),这样在下面调用方法的时候就不需要加括号了
result = models.UserList.objects.all()[page_obj.start:page_obj.end]
all_item = models.UserList.objects.all().count()
pager_str = page_obj.page_str(all_item,'/user_list/')
return render(request,'user_list.html',{'result':result,'pager_str':pager_str})
- 存在问题:
页码如何在前6页,页码会出现负数,如果页码在最后一页会出现无穷大,修改代码如下:
'''
如果总页数 <= 11 比如9页:
那么,还有必要让页码动起来吗?就没必要了直接显示总共页数就行了!start就是1,end就是9就行了
else:
如果当前页小宇6:
start:1
end:11
如果当前页大于6:
start:当前页-5
end:当前页+6
如果当前页+6 >总页数:
start:总页数-10
end:总页数
'''
#/usr/bin/env python
#-*- coding:utf-8 -*-
from django.shortcuts import render
from django.shortcuts import HttpResponse
import models
# Create your views here.
class Pager(object):
def __init__(self,current_page):
self.current_page = int(current_page)
#把方法伪造成属性(1)
@property
def start(self):
return (self.current_page-1)*10
@property
def end(self):
return self.current_page*10
def page_str(self,all_item,base_url):
all_page, div = divmod(all_item, 10)
if div > 0:
all_page += 1
pager_str = ""
# #默认可以看到的页码11个
#
# start = self.current_page - 5
# end = self.current_page + 6
#
# #把页面动态起来传入起始和结束
# for i in range(start, end):
#
# #判断是否为当前页
# if i == self.current_page:
# temp = '<a style="color:red;font-size:26px;padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)
# else:
# temp = '<a style="padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)
#
# # 把标签拼接然后返回给前端
# pager_str += temp
if all_page <= 11:
start = 1
end = all_page
else:
if self.current_page <= 6:
start = 1
end = 11 + 1
else:
start = self.current_page - 5
end = self.current_page + 6
if self.current_page + 6 > all_page:
start = all_page - 10
end = all_page + 1
#把页面动态起来传入起始和结束
for i in range(start, end):
#判断是否为当前页
if i == self.current_page:
temp = '<a style="color:red;font-size:26px;padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)
else:
temp = '<a style="padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)
# 把标签拼接然后返回给前端
pager_str += temp
return pager_str
def user_list(request):
current_page = request.GET.get('page',1)
page_obj = Pager(current_page)
#把方法改造成属性(2),这样在下面调用方法的时候就不需要加括号了
result = models.UserList.objects.all()[page_obj.start:page_obj.end]
all_item = models.UserList.objects.all().count()
pager_str = page_obj.page_str(all_item,'/user_list/')
return render(request,'user_list.html',{'result':result,'pager_str':pager_str})
- 给页码增加上一页、下一页
给页码生成一个列表每次生成后添加到列表之中,append默认是在最后添加,可以使用insert 在列表最前卖弄添加上一页,代码如下:
#/usr/bin/env python
#-*- coding:utf-8 -*-
from django.shortcuts import render
from django.shortcuts import HttpResponse
import models
# Create your views here.
class Pager(object):
def __init__(self,current_page):
self.current_page = int(current_page)
#把方法伪造成属性(1)
@property
def start(self):
return (self.current_page-1)*10
@property
def end(self):
return self.current_page*10
def page_str(self,all_item,base_url):
all_page, div = divmod(all_item, 10)
if div > 0:
all_page += 1
pager_list = []
if all_page <= 11:
start = 1
end = all_page
else:
if self.current_page <= 6:
start = 1
end = 11 + 1
else:
start = self.current_page - 5
end = self.current_page + 6
if self.current_page + 6 > all_page:
start = all_page - 10
end = all_page + 1
#把页面动态起来传入起始和结束
for i in range(start, end):
#判断是否为当前页
if i == self.current_page:
temp = '<a style="color:red;font-size:26px;padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)
else:
temp = '<a style="padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)
# 把标签拼接然后返回给前端
pager_list.append(temp)
#上一页
if self.current_page > 1:
pre_page = '<a href="%s?page=%d">上一页</a>' % (base_url, self.current_page - 1)
else:
# javascript:void(0) 什么都不干
pre_page = '<a href="javascript:void(0);">上一页</a>'
#下一页
if self.current_page >= all_page:
next_page = '<a href="javascript:void(0);">下一页</a>'
else:
next_page = '<a href="%s?page=%d">下一页</a>' % (base_url, self.current_page + 1)
pager_list.insert(0, pre_page)
pager_list.append(next_page)
return "".join(pager_list)
def user_list(request):
current_page = request.GET.get('page',1)
page_obj = Pager(current_page)
#把方法改造成属性(2),这样在下面调用方法的时候就不需要加括号了
result = models.UserList.objects.all()[page_obj.start:page_obj.end]
all_item = models.UserList.objects.all().count()
pager_str = page_obj.page_str(all_item,'/user_list/')
return render(request,'user_list.html',{'result':result,'pager_str':pager_str})