• 自定义分页器


    自定义分页器

    自定义分页器的使用,建立一个用来存储外来的组件(utils), 建一个py文件将代码直接拷贝过去

    # @Author   :SkyOcean  # @Time:2019/10/2914:06
    # @File     :mypage.py
    class Pagination(object):
        def __init__(self, current_page, all_count, per_page_num=5, pager_count=11):
            """
            封装分页相关数据
            :param current_page: 当前页:current_page = request.GET.get('page',1)
            :param all_count:    数据库中的数据总条数
            :param per_page_num: 每页显示的数据条数
            :param pager_count:  最多显示的页码个数
    
            用法:
            queryset = model.objects.all()
            page_obj = Pagination(current_page,all_count)
            page_data = queryset[page_obj.start:page_obj.end]
            获取数据用page_data而不再使用原始的queryset
            获取前端分页样式用page_obj.page_html
            """
            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)
    
    

    后端

     from app01.utils.mypage import Pagination
    使用封装好的分页器代
    def login(request):
        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]
    	return render(request,'login.html',locals())
    

    前端

    {% for book_obj in page_queryset %}
    	<p>{{ book_obj.title }}</p>
    {% endfor %}
    {{ page_obj.page_html|safe }}
    

    自定义分页器的分析过程

    views后端

    def index(request):
        # 1.获取用户想要访问的页码数
        current_page = request.GET.get('page',1)  # 如果没有page参数 默认就展示第一页
        # 转成整型
        current_page = int(current_page)
        # 2.每页展示10条数据
        per_page_num = 10
    
        # 3.定义起始位置和终止位置
        start_page = (current_page - 1) * per_page_num
        end_page = current_page * per_page_num
    
        # 4.统计数据的总条数
        book_queryset = models.Book.objects.all()
        all_count = book_queryset.count()
    
        # 5.求数据到底需要多少页才能展示完
        page_num, more = divmod(all_count,per_page_num)  # divmod(100,10)
        if more:
            page_num += 1
        # page_num就觉得了 需要多少个页码
        page_html = ''
        xxx = current_page  # xxx就是用户点击的数字
        if current_page < 6:
             current_page = 6
        for i in range(current_page-5,current_page+6):
            if xxx == i:
                page_html += '<li class="active"><a href="?page=%s">%s</a></li>'%(i,i)
            else:
                page_html += '<li><a href="?page=%s">%s</a></li>' % (i, i)
    
        book_queryset = book_queryset[start_page:end_page]
        return render(request,'index.html',locals())
    

    html前端

    <table class="table table-hover table-bordered">
        <thead>
        <tr>
            <th>id</th>
            <th>书名</th>
            <th>详情</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        {% for page in book_querset %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ page.title }}</td>
                <td>{{ page.addr }}</td>
                <td>
                    <a href="">添加</a>
                    <a href="">删除</a>
                </td>
            </tr>
    
        {% endfor %}
        </tbody>
    </table>
    <nav aria-label="Page navigation">
      <ul class="pagination">
        <li>
          <a href="#" aria-label="Previous">
            <span aria-hidden="true">&laquo;</span>
          </a>
        </li>
          {{ page_html|safe }}
        <li>
          <a href="#" aria-label="Next">
            <span aria-hidden="true">&raquo;</span>
          </a>
        </li>
      </ul>
    </nav>
    

    数据模型定义(批量操作数据)

    from django.db import models
    # Create your models here.
    class Test(models.Model):
        name = models.CharField(max_length=32, null=True, default=None)
        age = models.IntegerField(max_length=32, null=True, default=None)
    

    img

    在urls.py文件添加一个路径

    urlpatterns = [
        path('admin/', admin.site.urls),
        path("favicon.ico", RedirectView.as_view(url='static/favicon.ico')),
        re_path('^index/',views.index),
    ]
    

    在views.py添加数据

    批量添加单个字段

    def index(request):
        product_list_to_insert = list()
    	for i in range(1000):
            product_list_to_insert.append(models.Test(name='123'))
        models.Test.objects.bulk_create(product_list_to_insert)
        
    

    批量添加多个字段

    # ############### 添加数据 ###############    
    def index(request):
        import random
    
        product_list_to_insert = list()
        for x in range(100):
           #注意下面的添加方式 product_list_to_insert.append(models.Test(name='apollo' + str(x), age=random.randint(18, 89)))
        models.Test.objects.bulk_create(product_list_to_insert)
        return render(request, 'index.html')
    

    批量更新数据

    批量更新数据时,先进行数据过滤,然后再调用update方法进行一次性地更新。下面的语句将生成类似update....frrom....的SQL语句。
    # ############### 更新数据 ###############
    Test.objects.filter(name__contains='apollo1').update(name='Jack')
    

    批量删除数据

    批量更新数据时,先是进行数据过滤,然后再调用delete方法进行一次性删除。
    下面的语句讲生成类似delete from ... where ... 的SQL语句。
    # ############### 删除数据 ###############
    Test.objects.filter(name__contains='jack').delete()
    

    创建多对多表关系的三种方式

    方式1:全自动创建(推荐使用**)

    优点:好处在于 django orm会自动帮你创建第三张关系表
    缺点:但是它只会帮你创建两个表的关系字段(俩个book_id,author_id) 不会再额外添加字段
    虽然方便 但是第三张表的扩展性较差 无法随意的添加额外的字段

    class Book(models.Model):
        ...
        authors = models.ManyToManyField(to='Author')
    
    class Author(models.Models):
    	...
    

    方式2:纯手动(不推荐使用)

    自己手动添加外键

    优点:好处在于第三张表是可以任意的添加额外的字段

    缺点:不足之处是在于orm查询的时候,很多方法不支持,查询的时候非常的麻烦

    class Book(models.Model):
                    ...
                    
    class Author(models.Models):
    	...
                
    class Book2Author(models.Model):
    	book_id = models.ForeignKey(to='Book')
    	author_id = models.ForeignKey(to='Author')
    	create_time = models.DateField(auto_now_add=True)
    

    方式3半自动(推荐使用,扩展性高)

    3.半自动(推荐使用******)
    手动建表 但是你会告诉orm 第三张表是你自己建的
    orm只需要给我提供方便的查询方法
    第三种虽然可以使用orm查询方法,但是不支持使用下面的方法:
    add()
    set()
    remove()
    clear()

    class Book(models.Model):
        ...
        authors = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book','author'))#告诉django,是和那个表多对多关联,关联表是什么,关联的字段是什么
    class Author(models.Model):
        ...
        #books = models.ManyToManyField(to='Book', through='Book2Author', through_fields=('author', 'book'))
    class Book2Author(models.Model):
        book = models.ForeignKey(to='Book')
        author = models.ForeignKey(to='Author')
        create_time = models.DateField(auto_now_add=True)#建立额外的字段
    

    注意

    1. 半自动 一定要加两个额外的参数: through='Book2Author', through_fields=('book','author')
    2. 后面字段的顺序:由第三张表通过哪个字段查询单表 就把哪个字段放前面
    3. 在设计项目的时候 一定要给自己留后路 防止后续的迭代更新 ,因此推荐使用方法3

    Django的分页器(paginator)简介

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

    from django.core.paginator import Paginator

    Paginator对象:    paginator = Paginator(user_list, 10)
    # per_page: 每页显示条目数量
    # count:    数据总个数
    # num_pages:总页数
    # page_range:总页数的索引范围,如: (1,10),(1,200)
    # page:     page对象    
    page对象:page=paginator.page(1)
    # has_next              是否有下一页
    # next_page_number      下一页页码
    # has_previous          是否有上一页
    # previous_page_number  上一页页码
    # object_list           分页之后的数据列表
    # number                当前页
    # paginator             paginator对象
    

    应用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})
    

    模版层 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>
    

    扩展(可看)

    '''
        显示左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)
    
        #  如果页数十分多时,换另外一种显示方式
        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())
    
    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())
    
    
    <!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>
    
    
  • 相关阅读:
    linux(fedora) 下dvwa 建筑环境
    【ThinkingInC++】2、输入和输出流
    Caused by: java.lang.ClassNotFoundException: javax.transaction.TransactionManager
    SpringMVC注释启用
    XML wsdl soap xslt xsl ide
    一个解析RTSP 的URL函数
    PHP:header()函数
    jquery实现鼠标焦点十字效果
    拼出漂亮的表格
    Oracle中如何插入特殊字符:& 和 ' (多种解决方案)
  • 原文地址:https://www.cnblogs.com/SkyOceanchen/p/11761831.html
Copyright © 2020-2023  润新知