• 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

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

    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>
    前端显示页面
  • 相关阅读:
    四则运算单元测试
    四则运算2
    课堂记录
    软件工程第一课,设计简单小学四则运算
    阅读计计计计计计划
    团队开发——冲刺1.a
    博客园之用户体验
    软件项目风险评估计划
    《人月神话》读书笔记 第2篇
    课堂作业——找1
  • 原文地址:https://www.cnblogs.com/knighterrant/p/10292020.html
Copyright © 2020-2023  润新知