Django分页器和自定义分页器 一.自定义分页器  二. Django 分页器的使用

import copy

class Pagination():
    def __init__(self,request,current_page,all_data_num,each_page_data_num=10,max_page_num=11):
        #封装页面相关数据
        '''
        current_page:当前页
        data_num:数据总条数
        each_page:每页数据条数
        max_page_num:最大显示的页码数
        page_num: 总页数
       '''
        self.url_data= copy.deepcopy(request.GET)
         # page =1&a=1&b=2

        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1
        if current_page <1:
            current_page = 1


        self.current_page =current_page
        self.all_data_num = all_data_num  #100
        self.each_page_data_num =each_page_data_num  #
        self.max_page_num = max_page_num #总大显示的页码数
        # 计算总页数
        total_page_num,tmp = divmod(self.all_data_num,self.each_page_data_num)
        if tmp:
            total_page_num +=1
        self.total_page_num = total_page_num  #总页数

        self.page_count_half = int((self.max_page_num-1)/2)

    @property
    def start(self):
        return (self.current_page-1)*self.each_page_data_num

    @property
    def end(self):
        return self.current_page*self.each_page_data_num


    def page_html(self):
        #总页码 < 最大显示的页码数
        if self.total_page_num <self.max_page_num:
            page_start = 1
            page_end =self.total_page_num+1

        #总页码 > 最大显示的页码数
        else:

            if self.current_page <=self.page_count_half:
                page_start = 1
                page_end =self.max_page_num+1
            elif (self.current_page+self.page_count_half)>self.total_page_num:
                page_start=self.total_page_num-self.max_page_num+1
                page_end =self.total_page_num+1
            else:
                page_start =self.current_page-self.page_count_half
                page_end =self.current_page+self.page_count_half+1

        page_html_lst=[]

        #首页,上一页标签
        self.url_data["page"]=1
        frist_page ='<nav aria-label="Page navigation"><ul class="pagination"><li><a href="?%s">首页</a></li>'%(self.url_data.urlencode(),)
        page_html_lst.append(frist_page)
        self.url_data["page"] = self.current_page-1
        if self.current_page<=1:
            prev_page ='<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev_page = '<li><a href="?%s">上一页</a></li>'%(self.url_data.urlencode(),)
        page_html_lst.append(prev_page)

        #每页显示的页码

        for i in range(page_start,page_end):
            self.url_data["page"] = i
            if i == self.current_page:
                tmp ='<li class="active"><a href="?%s">%s</a></li>' % (self.url_data.urlencode(), i,)
            else:
                tmp ='<li><a href="?%s">%s</a></li>' % (self.url_data.urlencode(), i,)
            page_html_lst.append(tmp)

        self.url_data["page"] = self.current_page + 1
        if self.current_page >=self.total_page_num:
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?%s">下一页</a></li>' % (self.url_data.urlencode(),)
        page_html_lst.append(next_page)
        self.url_data["page"] =self.total_page_num
        last_page = '<li><a href="?%s">尾页</a></li></ul></nav>' % (self.url_data.urlencode(),)
        page_html_lst.append(last_page)

        return "".join(page_html_lst)

自定义分页器的使用:

  该分页器依赖bootstrapt 的样式 

  pagination = Pagination(参数)

  1. 最关键的两个参数:

    1.当前页的页码          当前页码   reuqest.GET.get("page")

    2.以及需要分页的数据条数

  2. 该分页器 能做的:

    1. 将数据分好页,且 通过该类的两个属性 ,可以得到当前页的数据范围 总数据进行切片 [pagination.start:  pagination.end],得到当前页的数据,可以通过循环展示的页面。

    2. pagination.page_html() 该方法,实现页码展示效果

保存搜索路径

1.   浏览器请求: http://127.0.0.1:8020/yema/?page=4&a=1&b=2&q=3

2.后端涉及到的知识点:

param = copy.deepcopy(request.GET)   # 此字典可以变  ,通过 param["page"] = 值 改变 page 的页码

param.urlencode()  #  把字典类型的数据转化成   此种格式的 数据   :page=4&a=1&b=2&q=3

Django分页器和自定义分页器
一.自定义分页器
 二. Django 分页器的使用

后端实现逻辑:自定义分页器

from  django.utils.safestring import mark_safe
import copy
class Pagination(object):

    def __init__(self,request,current_page,data_num,per_page_data_num,show_page_num):

        try:
            self.current_page = int(current_page)
        except Exception as e: #当前页码
            self.current_page = 1
        self.data_num = data_num # 数据总条数
        self.per_page_data_num = per_page_data_num #没页显示的数据条数
        self.show_page_num = show_page_num  # 显示的页码条数
        self.request = request

        #计算总页数 page_nums
        num,b = divmod(self.data_num,self.per_page_data_num)

        if b:
            self.page_nums = num+1
        else:
            self.page_nums = num

        self.half_range = int((self.show_page_num-1)/2)

    @property
    def start(self):
        start = (self.current_page-1)*self.per_page_data_num
        return start

    @property
    def end(self):
        end = self.current_page*self.per_page_data_num
        return end

    @property
    def page_range(self):
        # 显示的页面数  show_page_num  11

        #如果总页码数小于 show_page_num
        if self.page_nums<=self.show_page_num:
            page_range = range(1,self.page_nums+1)
        else: # 如果页面数大于show_page_num
            #如果当前页码数 +half 小于 show_page_num,就显示前show_page_num
            if (self.current_page+self.half_range)<= self.show_page_num:
                page_range = range(1,self.show_page_num+1)

             #如果当前页+half 大于 page_nums ,就显示最后show_page_num
            elif (self.current_page+self.half_range)>= self.page_nums:
                page_range = range(1,self.page_nums+1)[-self.show_page_num:]

            else:
                page_range = range(self.current_page-self.half_range,self.current_page+self.half_range)



        return page_range

    #页码的实现
    def page_html(self):
        param = copy.deepcopy(self.request.GET)
        #首页
        param["page"] = 1
        first_page= '<nav aria-label="Page navigation"><ul class="pagination"><li>' 
                    '<a href="?%s"><span aria-hidden="true">首页</span> </a></li>'%param.urlencode()
        #上一页
        param["page"] = self.current_page-1
        if self.current_page-1>0:
            per_page =  '<li><a href="?%s">'
                       '<span aria-hidden="true">上一页</span> </a></li>'%(param.urlencode())
        else:
            per_page = '<li><span aria-hidden="true" class="disabled">上一页</span></li>'

        page_body = ''

        #中间页

        for num in self.page_range:
            param["page"] = num
            if self.current_page == num:

                page_h ='<li class ="active"><a href="?%s" >%s</a></li>'%(param.urlencode(),num)

            else:
                page_h = '<li> <a href="?%s">%s</a> </li>' % (param.urlencode(), num)

            page_body+= page_h

        #下一页
        param["page"]=self.current_page+1
        if self.current_page<self.page_nums:
            next_page = '<li><a href="?%s" aria-label="Next">'
                        '<span aria-hidden="true">下一页</span></a></li>'%(param.urlencode())

        else:
            next_page = '<li><span aria-hidden="true" class="disabled">下一页</span>'

        #尾页
        param["page"] = self.page_nums
        last_page = '<li><a href="?%s"><span aria-hidden="true">尾页</span></a></li></ul></nav></li>'% param.urlencode()
        page_html = first_page+per_page + page_body + next_page+last_page

        return mark_safe(page_html)

 二. Django 分页器的使用

1.批量创建数据 

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

批量创建数据
    book_list=[]
    for i in range(1,101):

        book=Book(name="book%s"%i,price=random.randint(100,900))

        book_list.append(book)

    Book.objects.bulk_create(book_list)

2.django 分页器的用法

  #django 分页器的使用

    #总数据
    book_lst=Book.objects.all()
#创建分页器对象 paginator = Paginator(book_lst,10) #参数 : 总数据,每页需要放的数据条数

print("总数据条数:",paginator.count) # 200 print("总共分了多少页:",paginator.num_pages) # 20 print("页码范围:",paginator.page_range) # range(1,21) page =paginator.get_page(3) #取第 3 页的数据 # paginator.get_page(n) 拿到第 n 页 的数据 # for book in page: # print(book) print("是否有下一页",page.has_next()) # 第3 页 有下一页 返回的是布尔值 :True print("是否有上一页",page.has_previous()) # 第 3 页有上一页 返回的是布尔值 :True print("下一页的数字:",page.next_page_number()) # 取到第3页的下一页数字4 print("上一页的数字:",page.previous_page_number()) #取第3页的上一页 数字 2

3. 实例

paginator =Paginator(data_list,10) 

1.设计思路: 

先从地址栏 发请求 的思路  开始考虑问题     http://127.0.0.1:8000/index/?page=3

地址栏  通过一个 page=1 的键值对 ,通过发get的请求给后端服务器, 后端通过 current_page=  request.GET.get("page")  得到需要看的page数

通过  page_data = paginator .get_page(current_page) ,然后前端通过循环page_data 展示客户需要看的那一页数据

2. 设计 显示页码

后端逻辑:

   
    book_list = Book.objects.all()
    paginator = Paginator(book_list,2)


    current_page=int(request.GET.get("page",1))
    page = paginator.get_page(current_page)

    #  如果页数十分多时,换另外一种显示方式 ,
    if paginator.num_pages>11:  #页面最多显示的页码数   11表示:需要显示的页面码总数 ,以及上一页,下一页,首页 ,尾页

        if current_page-5<1:
            page_range=range(1,12)
        elif current_page+5>paginator.num_pages:
            page_range=range(paginator.num_pages-10,paginator.num_pages+1)
        else:
            page_range=range(current_page-5,current_page+6)
    else:
        page_range=paginator.page_range
    return render(request,"index.html",{"page":page,"page_range":page_range,"current_page":current_page})

模板HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <ul> {% for book in page %} <li>{{ book.title }}---{{ book.price }}</li> {% endfor %} </ul> <nav aria-label="Page navigation"> <ul class="pagination"> <li><a href="?page=1" aria-label="Previous"><span aria-hidden="true">首页</span></a></li> {% if page.has_previous %} <li><a href="?page={{ page.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">上一页</span></a></li> {% else %} <li class="disabled"><a aria-label="Previous"><span aria-hidden="true">上一页</span></a></li> {% endif %} {% for num in page_range %} {% if num == current_page %} <li class="active"><a href="?page={{ num }}">{{ num }}</a></li> {% else %} <li><a href="?page={{ num }}">{{ num }}</a></li> {% endif %} {% endfor %} <li> <a href="#" > <span aria-hidden="true">下一页</span> </a> </li> <li> <a href="#" > <span aria-hidden="true">尾页</span> </a> </li> </ul> </nav> </body> </html>

 2.django 分页器

from django.shortcuts import render
from .models import Book
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
import random
# Create your views here.
def index(request):

    #批量创建数据
    # book_list = []
    #
    # for i in range(1,101):
    #     book= Book(title="book_%s"%i,price=random.randint(100,600))
    #
    #     book_list.append(book)
    #
    # Book.objects.bulk_create(book_list)
    book_list = Book.objects.all()
    current_page = request.GET.get("page")

    #实例化分页器

    paginator = Paginator(book_list,9)
    num_pages= paginator.num_pages #能分多少页
    page_range = paginator.page_range # 页码范围
    page = paginator.get_page(current_page)
    show_books = page.object_list
    print(page.has_previous())


    #页码显示的个数 show_page_nums =11
    show_page_nums = 11
    if num_pages <show_page_nums: #num_pages<show_page_nums
        #展示所有的页码
        page_range = page_range
    else:
        #正常当前页算出左右的页面数:
        half_num = int((show_page_nums-1)/2)
        #分页数大于11时: num_pages>show_page_nums
            #当前页或等于half_num就显示前面的11页
        if int(current_page)<=half_num:
            #就显示 前 show_page_nums
            page_range = range(1,show_page_nums+1)

        elif (int(current_page)+half_num)>=num_pages:
            #就显示最后 show_page_nums 页
           page_range = range(1,num_pages+1)[-show_page_nums:]
        else:
            page_range = range((int(current_page)-half_num),(int(current_page)+half_num)+1)


    return render(request,"index.html",{"book_list":show_books,"page_range":page_range,"current_page":int(current_page),"page":page,})
后端逻辑
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
{% for book in book_list %}
    <div>{{ book.title }}--------------{{ book.price }}</div>
{% endfor %}

<nav aria-label="Page navigation">
    <ul class="pagination">
        <li>
            {% if page.has_previous %}
                <a href="?page={{ page.previous_page_number }}" aria-label="Previous">
                    <span aria-hidden="true">上一页</span>
                </a>
            {% else %}

                    <span aria-hidden="true" class="disabled"frd>上一页</span>

            {% endif %}

        </li>
        {% for num in page_range %}

            {% if current_page == num %}
                <li class="active"><a href="?page={{ num }}">{{ num }}</a></li>
            {% else %}
                <li><a href="?page={{ num }}">{{ num }}</a></li>
            {% endif %}
        {% endfor %}

        <li>
            {% if page.has_next %}
             <a href="?page={{ page.next_page_number }}" aria-label="Next">
                <span aria-hidden="true">下一页</span>
            </a>
                {% else %}
                <span aria-hidden="true" class="disabled">下一页</span>
            </a>
            {% endif %}

        </li>
    </ul>
</nav>

</body>
</html>
前端显示页面