django提供了分页功能接口,比自己用切片来实现方便很多。
利用django的Paginator分页类,加上booststrap美化前端,实现分页功能。
目标效果如下:
- a) 只显示n个标签页,如5。
b) 选中变色。
c) 上一页下一页功能。
d) 若当前选中第一页,则不再显示上一页标签。
e) 若当前选中最后页,则不再显示下一页。
Pagination reffer:https://docs.djangoproject.com/en/1.11/topics/pagination/
主要功能测试
PART1: 核心功能实现
-
1.1 django代码
1.1.1 models.py
from django.db import models
class Articles(models.Model):
title=models.CharField(max_length=32)
content=models.TextField()
def __str__(self):
return self.title
1.1.2 创建测试数据
from projectname.wsgi import *
from app01.models import *
for i in range(1,96):
title="title"+str(i)
content="text"+str(i)
Articles.objects.create(title=title,content=content)
1.1.3 views.py
from django.shortcuts import render,HttpResponse,redirect
from .models import Articles
from django.core.paginator import Paginator
def page_demo(request):
articles=Articles.objects.all()
paginator_obj=Paginator(articles,5) #每页5条
# print(paginator_obj.page_range)
request_page_num=request.GET.get('page',1)
# print(request_page_num)
page_obj=paginator_obj.page(request_page_num)
total_page_number=paginator_obj.num_pages
return render(request,'page_demo.html',{'page_obj':page_obj,'paginator_obj':paginator_obj})
1.1.4 url.py
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^page_demo/', views.page_demo),
]
1.2 前端代码
1.2.1 page_demo.html
Title
{% for article in page_obj %}
## {{ article.title }} ##
{{ article.content }}
{% endfor %}
{% for page_num in paginator_obj.page_range %}
{{ page_num }}
{% endfor %}
小tip: 页数列表paginator_obj.page_range 也可替换成page_obj.paginator.page_range 即由当前页obj关联。views函数可以不再向前端传递paginator_obj
1.2.1 页面
翻页
以上,功能已经实现,比较丑陋。下面进行页面美化和功能优化。
PART2 页面美化和功能优化
-
2.1 分页标签,显示5页
先写个分页标签显示功能,设定标签数,WEB_DISPLAY_PAGE值。
观察某搜索网站,当显示偶数页10页时,当前页前为5页,当前页后为4页。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# info: edit by infaaf
# blog: https://blog.51cto.com/13606158
def get_pages(totalpage=1,current_page=1):
"""
example: get_pages(10,1) result=[1,2,3,4,5]
example: get_pages(10,9) result=[6,7,8,9,10]
页码个数由WEB_DISPLAY_PAGE设定
"""
WEB_DISPLAY_PAGE = 5
front_offset = int(WEB_DISPLAY_PAGE / 2)
if WEB_DISPLAY_PAGE % 2 == 1:
behind_offset=front_offset
else:
behind_offset=front_offset -1
if totalpage < WEB_DISPLAY_PAGE:
return list(range(1,totalpage+1))
elif current_page<=front_offset:
return list(range(1,WEB_DISPLAY_PAGE+1))
elif current_page>=totalpage-behind_offset:
start_page=totalpage-WEB_DISPLAY_PAGE+1
return list(range(start_page,totalpage+1))
else:
start_page=current_page-front_offset
end_page=current_page+behind_offset
return list(range(start_page,end_page+1))
if __name__ == '__main__':
res=get_pages(10,1)
print(res)
2.2 views.py改写
from django.shortcuts import render,HttpResponse,redirect
from .models import Articles
from django.core.paginator import Paginator
# Create your views here.
from app01.mylib.paginator_disp_nums import get_pages
def page_demo(request):
articles=Articles.objects.all()
paginator_obj=Paginator(articles,5) #每页5条
# print(paginator_obj.page_range)
request_page_num=request.GET.get('page',1)
# print(request_page_num)
page_obj=paginator_obj.page(request_page_num)
total_page_number=paginator_obj.num_pages
print(total_page_number)
page_list=get_pages(int(total_page_number),int(request_page_num))
return render(request,'page_demo.html',{'page_obj':page_obj,'page_list':page_list})
2.3 前端页面中,分页部分加入bootstrap美化。
Title
{% for article in page_obj %}
## {{ article.title }} ##
{{ article.content }}
{% endfor %}
part3 更好的方式
自定义类,python django提供的Paginator欠缺以上标签页范围等,自己实现个差不多功能的。
有需要功能,再添加即可,方便扩展。
工具类
#/usr/bin/env python3
# author infaaf
# 20180314
class Paginator:
def __init__(self,obj_count=1,obj_perpage=1,pagetag_current=1,pagetag_dsp_count=1):
'''
:param obj_count: 获得 条目总数
:param obj_perpage: 定义 每页显示条目数
:param pagetag_current: 获得 当前页码
:param pagetag_dsp_count: 定义 显示多少个页码
'''
self.obj_count=obj_count
self.obj_perpage=obj_perpage
try:
pagetag_current=int(pagetag_current)
if pagetag_current < 1:
pagetag_current=1
self.pagetag_current=pagetag_current
except Exception as e:
self.pagetag_current=1
self.pagetag_dsp_count=pagetag_dsp_count
self.pagetag_all_count=self.last_page
@property
def obj_slice_start(self):
return (self.pagetag_current-1)*self.obj_perpage
@property
def obj_slice_end(self):
return self.pagetag_current* self.obj_perpage
@property
def has_prev_page(self):
return False if self.pagetag_current <= self.first_page else True
@property
def has_next_page(self):
return False if self.pagetag_current >= self.last_page else True
@property
def prev_page(self):
if self.pagetag_current==1:
return 1
elif self.pagetag_current > self.pagetag_all_count:
return self.pagetag_all_count
else:
return self.pagetag_current-1
@property
def next_page(self):
if self.pagetag_current >= self.pagetag_all_count:
return self.pagetag_all_count
else:
return self.pagetag_current+1
@property
def first_page(self):
return 1
@property
def last_page(self):
if self.obj_count % self.obj_perpage == 0:
pagecount=int(self.obj_count / self.obj_perpage)
else:
pagecount = int(self.obj_count / self.obj_perpage)+1
return pagecount
@property
def pagetag_range(self):
'''页码列表'''
start=1
end=1
#pagetag页码数 奇数偶数情况下,前后多少个不同。
if self.pagetag_dsp_count%2==1:
before=int(self.pagetag_dsp_count/2)
after=before
else:
before=int(self.pagetag_dsp_count/2)
after=before-1
if self.pagetag_all_count < self.pagetag_dsp_count:
start=1
end=self.pagetag_all_count+1
elif self.pagetag_current <= before: #当前页码过小时
start=1
end=self.pagetag_dsp_count+1
elif self.pagetag_current >= self.pagetag_all_count - after: #当前页码过大时
start=self.pagetag_all_count - self.pagetag_dsp_count +1
end=self.pagetag_all_count+1
else:
start=self.pagetag_current - before
end=self.pagetag_current + after +1
# print("logging %s %s %s"%(self.pagetag_current,self.pagetag_dsp_count,self.pagetag_dsp_count))
return range(start, end)
view
from django.shortcuts import render
# Create your views here.
from .lib.paginator import Paginator
art_list=[]
for i in range(1,200):
a="art_"+str(i)
art_list.append(a)
# '''
# :param obj_count: 获得 条目总数
# :param obj_perpage: 定义 每页显示条目数
# :param pagetag_current: 获得 当前页码
# :param pagetag_dsp_count: 定义 显示多少个页码
# '''
def pag(request):
obj_count=len(art_list)
obj_perpage=10
pagetag_current=request.GET.get('page',1)
pagetag_dsp_count=6
paginator=Paginator(obj_count,obj_perpage,pagetag_current,pagetag_dsp_count)
art_obj=art_list[paginator.obj_slice_start:paginator.obj_slice_end]
return render(request,'pag.html',{'art_obj':art_obj,'paginator':paginator})
html
Title
{% load admin_urls %}
{% for obj in art_obj %}
{{ obj }}
{% endfor %}