• Django中的分页器


    1 Django的分页器(paginator)简介

    在页面显示分页数据,需要用到Django分页器组件

    from django.core.paginator import Paginator

    paginator对象下的属性及其代表的意义,
    使用Paginator(QuerySet对象, 10)生成paginator对象的时候, 第二个参数表示一页显示的数据个数

    Paginator对象: paginator = Paginator(QuerySet对象, 10)
    
    # per_page: 每页显示条目数量
    
    # count: 数据总个数
    
    # num_pages:总页数
    
    # page_range:总页数的索引范围,如: (1,10),(1,200)
    
    # page: page对象

    paga对象: page对象得到的具体到哪一页的对象, 改对象下的参数如下:

    paginator和page两个对象可以看成是一本书, paginator对象是整本书而page是该书的具体的哪一页

    page对象:page=paginator.page(1)
    
    # has_next 是否有下一页
    
    # next_page_number 下一页页码
    
    # has_previous 是否有上一页
    
    # previous_page_number 上一页页码
    
    # object_list 分页之后的数据列表
    
    # number 当前页
    
    # paginator paginator对象

    在Django中批量向数据库中插入数据的方式:

    使用的主要方法: models.UserInfo.objects.bulk_create(objs,batch_size)

    def pagetest(request):
    
    # 批量插入数据
    
    # objes:对象列表,batch_size 一次插入数据的量
    
    ll=[]
    
    for i in range(100):
    
    # models.UserInfo.objects.create()
    
    ll.append(models.UserInfo(name='lqz%s'%i,age=i+1))
    
    ret=models.UserInfo.objects.bulk_create(ll,20)
    
    
    
    return HttpResponse('ok')

    2 应用View层

    from django.shortcuts import render,HttpResponse
    
    
    
    # Create your views here.
    
    from app01.models import *
    
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    
    
    def index(request):
    
    
    
    '''
    
    批量导入数据:
    
    
    
    Booklist=[]
    
    for i in range(100):
    
    Booklist.append(Book(title="book"+str(i),price=30+i*i))
    
    Book.objects.bulk_create(Booklist)
    
    '''

    '''
    
    分页器的使用:
    
    
    
    book_list=Book.objects.all()
    
    
    
    paginator = Paginator(book_list, 10)
    
    
    
    print("count:",paginator.count) #数据总数
    
    print("num_pages",paginator.num_pages) #总页数
    
    print("page_range",paginator.page_range) #页码的列表
    
    
    
    
    
    
    
    page1=paginator.page(1) #第1页的page对象
    
    for i in page1: #遍历第1页的所有数据对象
    
    print(i)
    
    
    
    print(page1.object_list) #第1页的所有数据
    
    
    
    
    
    page2=paginator.page(2)
    
    
    
    print(page2.has_next()) #是否有下一页
    
    print(page2.next_page_number()) #下一页的页码
    
    print(page2.has_previous()) #是否有上一页
    
    print(page2.previous_page_number()) #上一页的页码
    
    
    
    
    
    
    
    # 抛错
    
    #page=paginator.page(12) # error:EmptyPage
    
    
    
    #page=paginator.page("z") # error:PageNotAnInteger
    
    
    
    '''
    
    
    
    
    
    book_list=Book.objects.all()
    
    
    
    paginator = Paginator(book_list, 10)
    
    page = request.GET.get('page',1)
    
    currentPage=int(page)
    
    
    
    
    
    try:
    
    print(page)
    
    book_list = paginator.page(page)
    
    except PageNotAnInteger:
    
    book_list = paginator.page(1)
    
    except EmptyPage:
    
    book_list = paginator.page(paginator.num_pages)
    
    
    
    
    
    return render(request,"index.html",{"book_list":book_list,"paginator":paginator,"currentPage":currentPage})

    3 模版层 index.html

    <!DOCTYPE html>
    
    <html lang="en">
    
    <head>
    
    <meta charset="UTF-8">
    
    <title>Title</title>
    
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
    
    integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    
    </head>
    
    <body>
    
    
    
    <div class="container">
    
    
    
    <h4>分页器</h4>
    
    <ul>
    
    
    
    {% for book in book_list %}
    
    <li>{{ book.title }} -----{{ book.price }}</li>
    
    {% endfor %}
    
    
    
    </ul>
    
    
    
    
    
    <ul class="pagination" id="pager">
    
    
    
    {% if book_list.has_previous %}
    
    <li class="previous"><a href="/index/?page={{ book_list.previous_page_number }}">上一页</a></li>
    
    {% else %}
    
    <li class="previous disabled"><a href="#">上一页</a></li>
    
    {% endif %}
    
    
    
    
    
    {% for num in paginator.page_range %}
    
    
    
    {% if num == currentPage %}
    
    <li class="item active"><a href="/index/?page={{ num }}">{{ num }}</a></li>
    
    {% else %}
    
    <li class="item"><a href="/index/?page={{ num }}">{{ num }}</a></li>
    
    
    
    {% endif %}
    
    {% endfor %}
    
    
    
    
    
    
    
    {% if book_list.has_next %}
    
    <li class="next"><a href="/index/?page={{ book_list.next_page_number }}">下一页</a></li>
    
    {% else %}
    
    <li class="next disabled"><a href="#">下一页</a></li>
    
    {% endif %}
    
    
    
    </ul>
    
    </div>
    
    
    
    
    
    
    
    </body>
    
    </html>

    4 扩展

    当我们的页数比较少的时候,我们可以将所有的页数全部展现到屏幕上供用户选择, 但是当我们的页数过多的时候,就必须要考虑在页面中显示多少个页数合适, 然后其他的页数暂时隐藏起来,需要的时候再显示出来, 具体要求显示多少个根据需求来设定

    核心逻辑

    '''
    
    显示左5,右5,总共11个页,
    
    1 如果总页码大于11
    
    1.1 if 当前页码减5小于1,要生成1到12的列表(顾头不顾尾,共11个页码)
    
    page_range=range(1,12)
    
    1.2 elif 当前页码+5大于总页码,生成当前页码减10,到当前页码加1的列表(顾头不顾尾,共11个页码)
    
    page_range=range(paginator.num_pages-10,paginator.num_pages+1)
    
    1.3 else 生成当前页码-5,到当前页码+6的列表
    
    page_range=range(current_page_num-5,current_page_num+6)
    
    2 其它情况,生成的列表就是pageinator的page_range
    
    page_range=paginator.page_range
    
    
    
    '''
    逻辑代码实现:
    
    
    def index(request):
    
    
    
    book_list=Book.objects.all()
    
    paginator = Paginator(book_list, 15)
    
    # 从前端获取当前页
    
    page = request.GET.get('page',1)
    
    currentPage=int(page)
    
    
    
    # 如果页数十分多时,换另外一种显示方式
    
    # 我们下边实现的是左5右5的显示方式
    
    # 注意range的取值是顾头不顾尾的
    
    
    
    if paginator.num_pages>11:
    
    
    
    if currentPage-5<1:
    
    pageRange=range(1,11)
    
    elif currentPage+5>paginator.num_pages:
    
    pageRange=range(currentPage-5,paginator.num_pages+1)
    
    
    
    else:
    
    pageRange=range(currentPage-5,currentPage+5)
    
    
    
    else:
    
    pageRange=paginator.page_range
    
    
    
    
    
    try:
    
    print(page)
    
    book_list = paginator.page(page)
    
    except PageNotAnInteger:
    
    book_list = paginator.page(1)
    
    except EmptyPage:
    
    book_list = paginator.page(paginator.num_pages)
    
    
    
    
    
    return render(request,"index.html",locals())

    在views中的使用:
    ​​​页面较多的时候分页器在views中的使用

    def page_test(request):
    
    # book_list=[]
    
    # for i in range(100):
    
    # book=Book(name='book%s'%i,price=10+i,pub_date='2018-09-18',publish_id=1)
    
    # book_list.append(book)
    
    # Book.objects.bulk_create(book_list,10)
    
    book_list=Book.objects.all()
    
    # 生成paginator对象,传入书籍列表,每页10条数据
    
    paginator=Paginator(book_list,3)
    
    # 总页码数
    
    print(paginator.num_pages)
    
    # 页码列表
    
    print(paginator.page_range)
    
    # 总数据
    
    print(paginator.count)
    
    # 获取页面传来的页码
    
    current_page=int(request.GET.get('page',1))
    
    page_range=[]
    
    # 左5 右5
    
    
    
    # 获取页面传来的页码的page对象
    
    try:
    
    page=paginator.page(current_page)
    
    # print(page.has_next()) #是否有下一页
    
    # print(page.next_page_number()) #下一页的页码
    
    # print(page.has_previous()) #是否有上一页
    
    # print(page.previous_page_number()) #上一页的页码
    
    # 循环打印出当页对象
    
    for i in page:
    
    print(i)
    
    except Exception as e:
    
    current_page=1
    
    page = paginator.page(1)
    
    if paginator.num_pages>11:
    
    if current_page+5>paginator.num_pages:
    
    page_range=range(paginator.num_pages-10,paginator.num_pages+1)
    
    elif current_page-5<1:
    
    page_range=range(1,12)
    
    else:
    
    page_range=range(current_page-5,current_page+6)
    
    else:
    
    page_range=paginator.page_range
    
    
    
    
    
    
    
    return render(request,'page_test.html',locals())
    
    
    
    views

    页面较多时分页器在模板中的使用:

    <!DOCTYPE html>
    
    <html lang="en">
    
    <head>
    
    <meta charset="UTF-8">
    
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    
    <title>Title</title>
    
    </head>
    
    <body>
    
    
    
    <ul>
    
    
    
    {% for foo in page %}
    
    <li>{{ foo.name }}</li>
    
    
    
    {% endfor %}
    
    
    
    </ul>
    
    <nav aria-label="Page navigation">
    
    <ul class="pagination">
    
    {% if page.has_previous %}
    
    <li>
    
    <a href="/page_test/?page={{ page.previous_page_number }}" aria-label="Previous">
    
    <span aria-hidden="true">上一页</span>
    
    </a>
    
    </li>
    
    {% else %}
    
    <li class="disabled">
    
    <a href="#" aria-label="Previous">
    
    <span aria-hidden="true">上一页</span>
    
    </a>
    
    </li>
    
    {% endif %}
    
    
    
    {% for foo in page_range %}
    
    {% if current_page == foo %}
    
    <li class="active"><a href="/page_test/?page={{ foo }}">{{ foo }}</a></li>
    
    {% else %}
    
    <li><a href="/page_test/?page={{ foo }}">{{ foo }}</a></li>
    
    {% endif %}
    
    
    
    {% endfor %}
    
    {% if page.has_next %}
    
    <li>
    
    <a href="/page_test/?page={{ page.next_page_number }}" aria-label="Next">
    
    <span aria-hidden="true">下一页</span>
    
    </a>
    
    </li>
    
    {% else %}
    
    <li class="disabled">
    
    <a href="#" aria-label="Next">
    
    <span aria-hidden="true">下一页</span>
    
    </a>
    
    </li>
    
    
    
    {% endif %}
    
    
    
    </ul>
    
    </nav>
    
    
    
    
    
    </body>
    
    </html>
    
    
    
    模版

     2、第三方使用版

    class Pagination(object):
        """自定义分页(Bootstrap版)"""
        def __init__(self, current_page, total_count, base_url, per_page=10, max_show=11):
            """
            :param current_page: 当前请求的页码
            :param total_count: 总数据量
            :param base_url: 请求的URL
            :param per_page: 每页显示的数据量,默认值为10
            :param max_show: 页面上最多显示多少个页码,默认值为11
            """
            try:
                self.current_page = int(current_page)
            except Exception as e:
                # 取不到或者页码数不是数字都默认展示第1页
                self.current_page = 1
            # 定义每页显示多少条数据
            self.per_page = per_page
            # 计算出总页码数
            total_page, more = divmod(total_count, per_page)
            if more:
                total_page += 1
            self.total_page = total_page
            # 定义页面上最多显示多少页码(为了左右对称,一般设为奇数)
            self.max_show = max_show
            self.half_show = max_show // 2
            self.base_url = base_url
    
        @property
        def start(self):
            return (self.current_page-1) * self.per_page
    
        @property
        def end(self):
            return self.current_page * self.per_page
    
        def page_html(self):
            # 计算一下页面显示的页码范围
            if self.total_page <= self.max_show:  # 总页码数小于最大显示页码数
                page_start = 1
                page_end = self.total_page
            elif self.current_page + self.half_show >= self.total_page:  # 右边越界
                page_end = self.total_page
                page_start = self.total_page - self.max_show
            elif self.current_page - self.half_show <= 1:  # 左边越界
                page_start = 1
                page_end = self.max_show
            else:  # 正常页码区间
                page_start = self.current_page - self.half_show
                page_end = self.current_page + self.half_show
            # 生成页面上显示的页码
            page_html_list = []
            page_html_list.append('<nav aria-label="Page navigation"><ul class="pagination">')
            # 加首页
            first_li = '<li><a href="{}?page=1">首页</a></li>'.format(self.base_url)
            page_html_list.append(first_li)
            # 加上一页
            if self.current_page == 1:
                prev_li = '<li><a href="#"><span aria-hidden="true">«</span></a></li>'
            else:
                prev_li = '<li><a href="{}?page={}"><span aria-hidden="true">«</span></a></li>'.format(
                    self.base_url, self.current_page - 1)
            page_html_list.append(prev_li)
            for i in range(page_start, page_end + 1):
                if i == self.current_page:
                    li_tag = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.base_url, i)
                else:
                    li_tag = '<li><a href="{0}?page={1}">{1}</a></li>'.format(self.base_url, i)
                page_html_list.append(li_tag)
            # 加下一页
            if self.current_page == self.total_page:
                next_li = '<li><a href="#"><span aria-hidden="true">»</span></a></li>'
            else:
                next_li = '<li><a href="{}?page={}"><span aria-hidden="true">»</span></a></li>'.format(
                    self.base_url, self.current_page + 1)
            page_html_list.append(next_li)
            # 加尾页
            page_end_li = '<li><a href="{}?page={}">尾页</a></li>'.format(self.base_url, self.total_page)
            page_html_list.append(page_end_li)
            page_html_list.append('</ul></nav>')
            return "".join(page_html_list)
    封装保存版
    
    view中
    def publisher_list(request):
        # 从URL中取当前访问的页码数
        current_page = int(request.GET.get('page'))
        # 比len(models.Publisher.objects.all())更高效
        total_count = models.Publisher.objects.count()
        page_obj = Pagination(current_page, total_count, request.path_info)
        data = models.Publisher.objects.all()[page_obj.start:page_obj.end]
        page_html = page_obj.page_html()
        return render(request, "publisher_list.html", {"publisher_list": data, "page_html": page_html})
    
    封装保存版使用示例

    自定义分页器的拷贝及使用

    """
    当我们需要使用到非django内置的第三方功能或者组件代码的时候
    我们一般情况下会创建一个名为utils文件夹 在该文件夹内对模块进行功能性划分
        utils可以在每个应用下创建 具体结合实际情况
    
    我们到了后期封装代码的时候 不再局限于函数
    还是尽量朝面向对象去封装
    
    我们自定义的分页器是基于bootstrap样式来的 所以你需要提前导入bootstrap
        bootstrap 版本 v3
        jQuery        版本 v3
    """
    # 后端
    book_queryset = models.Book.objects.all()
    current_page = request.GET.get('page',1)
    all_count = book_queryset.count()
    # 1 传值生成对象
    page_obj = Pagination(current_page=current_page,all_count=all_count)
    # 2 直接对总数据进行切片操作
    page_queryset = book_queryset[page_obj.start:page_obj.end]
    # 3 将page_queryset传递到页面 替换之前的book_queryset
    
    
    # 前端
    {% for book_obj in page_queryset %}
        <p>{{ book_obj.title }}</p>
        <nav aria-label="Page navigation">
    </nav>
    {% endfor %}
    {#利用自定义分页器直接显示分页器样式#}
    {{ page_obj.page_html|safe }}
    每天逼着自己写点东西,终有一天会为自己的变化感动的。这是一个潜移默化的过程,每天坚持编编故事,自己不知不觉就会拥有故事人物的特质的。 Explicit is better than implicit.(清楚优于含糊)
  • 相关阅读:
    使用python自带的http server共享文件
    vim常用快捷键与快捷操作
    wordpress 安装中文插件提示:To perform the requested action, WordPress needs to access your web server. Please enter your FTP cr
    python async异步编程,await后接task(三)
    虚拟机下ubuntu使用df命令查看磁盘空间小于实际空间
    python线程池
    使用Redis连接错误处理It was not possible to connect to the redis server(s);to create a disconnected multiple
    Sqlite数据库设置密码小工具
    [转]netcore一键部署到linux服务器以服务方式后台运行
    C#3种常见的定时器(多线程)
  • 原文地址:https://www.cnblogs.com/kylin5201314/p/13966251.html
Copyright © 2020-2023  润新知