django中的自定义分页器

1.什么是自定义分页器

当我们需要在前端页面展示的数据太多的时候,我们总不能将数据展示在一页上面吧!这时,我们就需要自定义一个分页器,将数据分成特定的页数进行展示,每一页展示固定条数的数据!

image

2.为什么要用自定义分页器

如上所说:为了将数据分成多页进行展示,分别阅读,方便查询!

image

3.如何使用自定义分页器

3.1 自定义分页器推导过程

虽然!我们有一个封装好的分页器源码,用的时候只需要cv大法就行,但是作为一名优秀的程序猿!!我们还是需要知道底层的逻辑是不是!!
image

我们需要明确的是,前端向后端请求的常用方式为get和post请求。分页的时候,我们应该采用get请求的方式给后端传输您需要转到的页数!!

其次我们还需要知道一个点,queryset对象是支持索引取值和切片操作的,但是不支持负数索引情况。

接下来,我们来推导一下分页器的形成的逻辑:

current_page = request.GET.get("page",1)  # 获取用户想访问的页码  如果没有 默认展示第一页
try:  # 由于后端接受到的前端数据是字符串类型所以我们这里做类型转换处理加异常捕获
  current_page = int(current_page)
except Exception as e:
  current_page = 1
# 还需要定义页面到底展示几条数据
per_page_num = 10  # 一页展示10条数据

# 需要对总数据进行切片操作 需要确定切片起始位置和终止位置
start_page = ? 
end_page = ?
"""
下面需要研究current_page、per_page_num、start_page、end_page四个参数之间的数据关系
per_page_num = 10
current_page                start_page                  end_page
    1                           0                           10
    2                           10                          20
    3                           20                          30  
    4                           30                          40

per_page_num = 5
current_page                start_page                  end_page
    1                           0                           5
    2                           5                           10
    3                           10                          15  
    4                           15                          20
可以很明显的看出规律
start_page = (current_page - 1) * per_page_num
end_page =  current_page* per_page_num
"""

我们研究完当前页(current_page)、每页展示的数据条数(per_page_num)、每页数据的起始位置(start_page)和结束位置(end_page)之后,我们还需要知道的最重要的一点是:

一共需要从数据库取出的数据一共有多少条!!!

image

此时,我们就需要用到python中的一个内置方法divmod:它是功能是一个数除以另一个数时,返回余数和商!!如:

>>> divmod(100,10)
(10, 0)  # 10页
>>> divmod(101,10)
(10, 1)  # 11页
>>> divmod(99,10)
(9, 9)  # 10页
# 余数只要不是0就需要在第一个数字上加一

我们可以用它来判断我们一共需要多少页!

后端自定义分页器逻辑详解:

def book(request):
    if request.method == 'GET':
        current_page = request.GET.get('page',1) # 获取用户需要访问的页面,如果没有默认返回1
    try:   #异常捕获,因为前端返回的都是字符串,需要把他们都转成数字类型,方便下面做运算操作
        current_page = int(current_page)
    except Exception as e:
        current_page = 1  # 用户输入啥字母等也默认为1
    per_page_num = 10  #每页展示多少条数据
    start_page = (current_page - 1) * per_page_num  #当前页数起始数据
    end_page = current_page * per_page_num  #当前页结束数据
    book_num = models.Book.objects.all() #将所有数据查询出来
    all_count = book_num.count()  # 统计一共有多少数据
    num,more = divmod(all_count,per_page_num)  #divmod方法计算需要的总页数
    if more:
        all_page = num + 1 #more为余数,余为0,则刚刚好是num页数,不为0,则页数加1
    # 然后我们需要在html页面的分页器标签部分,for循环一下总共需要的num页数,但是有一个问题是,前端无法使用range()
    # 这就需要我们在后端进行循环,再传到前端
    html = ''
    a = current_page # 为了下面页码高亮调整
    if current_page <6:  #当页面小于6时,固定在6上面,为下面的for处理不出现页码负数
        current_page = 6
    # 访问第6页时,只会显示当前页-5和+6的底部页码数,但是当页面小于6时,页码会出现0甚至负数,所有我们需要对页面进行一个设置,就是上述的a
    for i in range(current_page-5,current_page+6):
        if a == i:
            # 当前页的页面高亮显示
            html += '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i)
        else:
            html += '<li><a href="?page=%s">%s</a></li>' % (i, i)
    book_queryset = book_num[start_page:end_page]
    return render(request,'book.html',locals())

前端页面部分:
<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
      </a>
    </li>
        {{ html|safe }}
    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">&raquo;</span>
      </a>
    </li>
  </ul>
</nav>

3.2 自定义分页器封装代码

封装好的分液器
class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param pager_count:  最多显示的页码个数
        """
        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_count = all_count
        self.per_page_num = per_page_num

        # 总页码
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager

        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

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

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

    def page_html(self):
        # 如果总页码 < 11个:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 总页码  > 11
        else:
            # 当前页如果<=页面上最多显示11/2个页码
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 当前页大于5
            else:
                # 页码翻到最后
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        # 添加前面的nav和ul标签
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加标签
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)

3.3 封装好分页器的使用

后端

# 先导入自己封装好的分液器模块,如何在使用
 def get_book(request):
   book_list = models.Book.objects.all()
   current_page = request.GET.get("page",1)
   all_count = book_list.count()
   page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
   page_queryset = book_list[page_obj.start:page_obj.end]
   return render(request,'booklist.html',locals())

前端

<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            {% for book in page_queryset %}
            <p>{{ book.title }}</p>
            {% endfor %}
            {{ page_obj.page_html|safe }}
        </div>
    </div>
</div>

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:django中的自定义分页器 - Python技术站

(0)
上一篇 2023年4月2日
下一篇 2023年4月2日

相关文章

  • cpu详解

    1.cpu的指令集和分类 1.1cpu的指令集 cpu的指令集指的是:控制计算机硬件的一系列命令。 指令集可以分为: 1.精简指令集:更短、更稳定,每条指令集运行的时间更短2.复杂指令集:可以完成更复杂的功能。需要花费的时间更长 1.2cpu的分类 cpu按照指令集可以分为:精简指令集cpu和复杂指令集cpu 2.x86-64位的概念 x86针对的是cpu的…

    2023年4月2日
    00
  • django中有关ajax的部分

    Django_ajax 1 简介 AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求; 异步交互:客户…

    Python开发 2023年4月2日
    00
  • input与print语法

    1.input输入语法 input是用来接收用户输入的一种语法,实现计算机与用户之间的交互,改方法有一个返回值,返回的是用户输入的字符串! 语法:res = input(‘请输入您的账号:’) 在python3中,用户输入的数据类型将会被全部转成字符串类型。在python2中,用户输入什么数据类型,程序就会转成什么类型,指的注意的是,用户假如输入的数据类型错…

    Python开发 2023年4月2日
    00
  • 面向对象高级–反射、内置方法和元类

    1.反射 1.1什么是反射 python是一门动态语言,而反射机制被视为动态语言的关键! 反射机制指的是:在程序的运行过程中,动态的获取程序的信息和对象的功能! ‘动态’:指一开始不知道程序的信息和对象的功能,只有等到运行到那的时候才会动态获取!!! 比如:x=18 在程序运行的时候,python才会通过反射机制动态的获取到这个值是整型,并不需要一开始定义的…

    Python开发 2023年4月2日
    00
  • 基础数据类型之集合

    1.集合的定义 在{}内用逗号分开多个元素,多个元素满足以下三个条件: 1.集合元素必须是不可变类型2.集合元素无序3.集合内元素没有重复(打印出来会自动去重) d = {} 默认是定义空字典 需要定义空集合,需要使用s = set() 2,集合的作用 (1)关系运算 # 如何取出这两个人共同的朋友呢? friend1=[‘zhang’,’yang’,’li…

    Python开发 2023年4月2日
    00
  • 小程序发布流程、小程序进度条组件、修改data里的局部数据、小程序api位置设置、首页瀑布流展示

    发布 发布流程的问题 方式一 1. 打开图片进行本地预览 2. 输入文字 & 选择相应的信息 3. 点击发布按钮 3.1 将本地图片上传到 腾讯云对象存储中COS(oss),并将COS中的图片地址返回。 3.2 将COS中的图片URL和文字等信息一起提交到后台。 BUG: 在3.2步骤时可能拿不到COS中的图片。 function onClickSu…

    Python开发 2023年3月31日
    00
  • 如何制作验证码

    推导步骤1:在img标签的src属性里放上验证码的请求路径 补充1.img的src属性: 1.图片路径 2.url 3.图片的二进制数据 补充2:字体样式 我们计算机上之所以可以输出各种各样的字体样式,其内部其实对应的是一个个以.ttf结尾的文件 由于img的src属性里可以放图片的二进制数据,因此我们可以在src里放上图片的请求路径,返回的是一个图片的二进…

    Python开发 2023年4月2日
    00
  • 基础数据类型之数字和字符串

    1.数字类型 数字类型的数据可以相互的进行+-/*、也可以进行相互的比较(<>=) 1.1整型int age = 18 记录年龄等整数 print(type(age))# int类型 int()方法可以将其他类型的数据转换成int类型 1.1.2二、八、十六进制的相互转换 1.十进制《—》二进制 # bin()方法 print(bin(11)…

    Python开发 2023年4月2日
    00
合作推广
合作推广
分享本页
返回顶部