zoukankan      html  css  js  c++  java
  • Django 之 分页和序列化

    分页

    一、Django内置分页

    views.py
    from django.shortcuts import render
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    L = []
    for i in range(999):
        L.append(i)       # 模拟数据库 生成数据
    
    def index(request):
        current_page = request.GET.get('page')  # 通过get请求得到当前请求的页数
    
        paginator = Paginator(L, 10)            # 实例化传入俩个参数(所有数据,当页显示条数)
        # per_page: 每页显示条目数量
        # count:    数据总个数
        # num_pages:总页数
        # page_range:总页数的索引范围,如: (1,10),(1,200)
        # page:     page对象
        try:
            posts = paginator.page(current_page)# 传入当前页码,观源码可得实例化了一个Page对象
            # has_next              是否有下一页
            # next_page_number      下一页页码
            # has_previous          是否有上一页
            # previous_page_number  上一页页码
            # object_list           分页之后的数据列表
            # number                当前页
            # paginator             paginator对象
        except PageNotAnInteger:    # 不是数字
            posts = paginator.page(1)
        except EmptyPage:           # 超出页码范围
            posts = paginator.page(paginator.num_pages)
        return render(request, 'index.html', {'posts': posts})  # posts封装了一些方法
    
    INDEX.HTML
    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <ul>
        {% for item in posts %}
            <li>{{ item }}</li>
        {% endfor %}
    </ul>
    
    <div class="pagination">
          <span class="step-links">
            {% if posts.has_previous %}
                <a href="?p={{ posts.previous_page_number }}">上一页</a>
            {% endif %}
              <span class="current">
                Page {{ posts.number }} of {{ posts.paginator.num_pages }}.  
              </span>
              {% if posts.has_next %}
                  <a href="?p={{ posts.next_page_number }}">下一页</a>
              {% endif %}
          </span>
    
    </div>
    </body>
    </html>
    

    那么、Django的内置分页基本俩个类实现、并封装了一些方法来使用、此时并不能满足有一些的需求

    二、Django内置分页的拓展

    拓展内置分页views.py
    from django.shortcuts import render
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    user = []
    for i in range(1, 1001):
        dic = {'name': 'root' + str(i), 'pwd': i}
        user.append(dic)
    
    
    class DiyPaginator(Paginator):
        def __init__(self, current_page,max_pager_num, *args, **kwargs):
            """
            :param current_page:  当前页码
            :param max_pager_num: 显示页码个数的最大值
            :param args:
            :param kwargs:
            """
            self.current_page = int(current_page)
            self.max_pager_num = int(max_pager_num)
            super(DiyPaginator,self).__init__(*args,**kwargs)
    
        def pager_num_range(self):
            # 需要的参数
            # 当前页码    self.current_page
            # 页码数量    self.max_pager_num
            # 总页数      self.num_pages
    
            # 如果总页数小于页码个数最大值的情况
            if self.num_pages < self.max_pager_num:
                return range(1,self.num_pages+1)     # 返回 从 1 到 总页数
    
            # 如果总页数大于页码数量且当前所选页码小于页码数量的一半    
            part = self.max_pager_num//2
            if self.current_page <= part:
                return range(1,self.max_pager_num+1) # 返回 从 1 到 页码个数最大值
    
            # 如果当前页码加一半的页码 大于 总页数
            if (self.current_page+part) > self.num_pages:
                # 返回 从总页数-最大页码数 到 总页数      range的用法在此不作解释
                # 例如 96页+5页 超出总页数 则返回的范围是 从 总页数-最大页码数量+1 到 总页数+1    
                return range(self.num_pages-self.max_pager_num+1,self.num_pages+1)
    
            # 其余情况从 当前页码减去显示页码的平均值开始  到 当前页码加显示页码的平均值(并加一)结束
            return range(self.current_page-part,self.current_page+part+1)
    
    
    def index(request):
        p = request.GET.get('page')
        start = (int(p)-1)*10
        end = int(p)*10
        data = user[start:end]
        return render(request,'index.html',{'data':data,'user':user})
    
    
    def index1(request):
        current_page = request.GET.get('page')
        paginator = DiyPaginator(current_page, 9, user, 10)
        # Paginator所封装的方法
        # per_page: 每页显示条目数量
        # count:    数据总个数
        # num_pages:总页数
        # page_range:总页数的索引范围,如: (1,10),(1,200)
        # page:     page对象
        try:
            posts = paginator.page(current_page)
            # has_next              是否有下一页
            # next_page_number      下一页页码
            # has_previous          是否有上一页
            # previous_page_number  上一页页码
            # object_list           分页之后的数据列表
            # number                当前页
            # paginator             paginator对象
        except PageNotAnInteger:      # 不是整形数字
            posts = paginator.page(1)
        except EmptyPage:             # 如果是空值
            posts = paginator.page(paginator.num_pages)
    
        return render(request,'index1.html',{'posts':posts})
    
    拓展内置分页HTML
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <ul>
            {% for row in posts.object_list %}
                <li>{{ row.name }}-{{ row.pwd }}</li>
            {% endfor %}
        </ul>
        {% include 'include/pager.html' %}
    </body>
    </html>
    
    ##################################
    include 组件代码
    
    {% if posts.has_previous %}
        <a href="/index1?page={{ posts.previous_page_number }}">上一页</a>
    {% endif %}
    
    {% for num in posts.paginator.pager_num_range %}
        {% if num == posts.number %}
            <a style="color: red;font-size: 20px" href="/index1?page={{ num }}">{{ num }}</a>
        {% else %}
            <a href="/index1?page={{ num }}">{{ num }}</a>
        {% endif %}
    {% endfor %}
    
    {% if posts.has_next %}
        <a href="/index1?page={{ posts.next_page_number }}">下一页</a>
    {% endif %}
    <span>
        当前页:{{ posts.number }}  总页数:{{ posts.paginator.num_pages }}
    </span>
    

    三、自定义分页(适用于任何地方)

    • 创建处理分页数据的类
    • 根据分页数据获取数据
    • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]或者额外的作出一些拓展也可以

    创建处理分页数据的类时,大致也需要四个参数(详情观看类构造方法)

      1、为了减少服务器内存的负载,不再获取所有数据的,而是获得所有数据的总个数,然后再根据索引查数据库的内容

      2、当前页码

      3、每页显示的行数

      4、页码显示的数量

    对于页数的显示大致也可以归类为三种情况(详情观看类中page_num_range函数)

      1、计算的总页数小于页码显示的数量

      2、计算的总页数大于页码显示的数量

        A、当前页数小于页码数量的一半

        B、当前页数加页码数量的一半超出总页数的范围

      3、正常情况

        从 当前页数 减 一半页码数量 到 当前页数 加 一半页码数量

     

    自定义分页
    class Pagination(object):
        def __init__(self,totalCount,currentPage,perPageItemNum=10,maxPageNum=9):
            """
            :param totalCount:     所有数据总个数
            :param currentPage:    当前页数
            :param perPageItemNum: 每页显示行数
            :param maxPageNum:     最多显示页码个数
            """
            self.total_count = totalCount
            # 对当前的页码进行一次异常捕获
            try:
                currentPage = int(currentPage)
                if currentPage <= 0:
                    currentPage = 1
                self.current_page = currentPage
            except Exception:
                self.current_page = 1
            self.per_page_item_num = perPageItemNum
            self.max_page_num = maxPageNum
    
        @property
        def start(self):
            # 数据索引开始的值
            return (self.current_page-1) * self.per_page_item_num
    
        @property
        def end(self):
            # 数据索引结束的值
            return self.current_page * self.per_page_item_num
    
        @property
        def num_pages(self):
            """
            总页数
            :return:
            """
            # 得商取余得内置函数
            x, o = divmod(self.total_count,self.per_page_item_num)
            if o == 0:
                return x
            return x + 1
    
        @property
        def page_num_range(self):
            if self.num_pages < self.max_page_num:
                return range(1, self.num_pages+1)
    
            part = self.max_page_num//2
            if self.current_page <= part:
                return range(1,self.max_page_num+1)
    
            if (self.current_page+part) > self.num_pages:
                return range(self.num_pages-self.max_page_num+1, self.num_pages+1)
            return range(self.current_page-part, self.current_page+part+1)
    
        def page_str(self):
            page_list = []
    
            first = "<li><a href='/index2/?page=1'>首页</a></li>"
            page_list.append(first)
    
            if self.current_page == 1:
                prev_page = "<li><a href='#'>上一页</a></li>"
            else:
                prev_page = "<li><a href='/index2/?page=%s'>上一页</a></li>" %(self.current_page-1)
            page_list.append(prev_page)
    
            for i in self.page_num_range:
                if i == self.current_page:
                    temp = "<li class='active'><a href='/index2/?page=%s'>%s</a></li>" %(i,i)
                else:
                    temp = "<li><a href='/index2/?page=%s'>%s</a></li>" % (i, i)
                page_list.append(temp)
    
            if self.current_page == self.num_pages:
                next_page = "<li><a href='#'>下一页</a></li>"
            else:
                next_page = "<li><a href='/index2/?page=%s'>下一页</a></li>" %(self.current_page+1)
            page_list.append(next_page)
    
            last = "<li><a href='/index2/?page=%s'>尾页</a></li>" %self.num_pages
            page_list.append(last)
    
            return ''.join(page_list)
    
    自定义分页views.py
    def index2(request):
        from page.diypage import Pagination
        current_page = request.GET.get('page')
        page_obj = Pagination(1000,current_page)
    
        data_list = user[page_obj.start:page_obj.end]
        return render(request,'index2.html',{
            'data' : data_list,
            'page_obj' : page_obj
        })
    

     

    自定义分页HTML
    # 本页面引用了bootstrap样式
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css" />
    </head>
    <body>
        <ul>
            {% for row in data %}
                <li>{{ row.name }}-{{ row.pwd }}</li>
            {% endfor %}
        </ul>
        {% for i in page_obj.pager_num_range %}
            <a href="/index2/?page={{ i }}">{{ i }}</a>
        {% endfor %}
        <hr/>
    
        <ul class="pagination pagination-sm">
            {{ page_obj.page_str|safe }}
          </ul>
        <div style="height: 300px;"></div>
    </body>
    </html>
    

    序列化

    序列化是将对象状态转换为可保持或传输的格式的过程

      反序列化是指将存储在存储媒体中的对象状态装换成对象的过程 

      例如游戏都有存档的功能、再次开始的时候只需读档即可(这即是一个序列化与反序列的过程)

      序列化也可以将一个对象传递到另一个地方的

      关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。

    1、serializers 

    from django.core import serializers
      
    ret = models.BookType.objects.all()
      
    data = serializers.serialize("json", ret)
    

    2、json.dumps  

    import json
      
    #ret = models.BookType.objects.all().values('caption')
    ret = models.BookType.objects.all().values_list('caption')
      
    ret=list(ret)
      
    result = json.dumps(ret)
    
  • 相关阅读:
    _ 下划线 Underscores __init__
    Page not found (404) 不被Django的exception中间件捕捉 中间件
    从装修儿童房时的门锁说起
    欧拉定理 费马小定理的推广
    线性运算 非线性运算
    Optimistic concurrency control 死锁 悲观锁 乐观锁 自旋锁
    Avoiding Full Table Scans
    批量的单向的ssh 认证
    批量的单向的ssh 认证
    Corrupted MAC on input at /usr/local/perl/lib/site_perl/5.22.1/x86_64-linux/Net/SSH/Perl/Packet.pm l
  • 原文地址:https://www.cnblogs.com/sunkai1993/p/6555743.html
Copyright © 2011-2022 走看看