zoukankan      html  css  js  c++  java
  • Django框架之ORM的相关操作之分页(六)

    分页是每个项目必不可少要写的一个功能,该篇文章就将记录一下使用ORM写分页的过程。

    假设我们的数据库里面需要显示一些数据,而这个表中的数据大约有几千条数据,那么我们不可能将所有的数据都显示出来,那么就需要使用分页来显示一部分数据,使用页数来进行翻页。在下面这个过程,我以一个demo的形式进行叙述。

    1.要想有许多数据,就要先创建一个存储数据的表,下面就使用模型类创建一个表。

    class TeacherTest(models.Model):
        id=models.AutoField(primary_key=True)
        name=models.CharField(max_length=20)

    可以看到,这个表创建成功后有两个字段,第一个字段是id,第二个字段是name。

    2.分页可以说分为两大部分,第一部分就是考虑显示部分数据在界面上,第二部分就是考虑页码如何写。如果想象不出是什么样子,可以参考一下博客园的分页,如下图:

    首先考虑第一部分:如何显示部分数据在前端上,而不是显示表中所有的数据。这种情况下,我们会考虑使用切片的知识,比如:字符串str1="abcdefg"想要获取到abc怎么办呢,就使用切片,str2=str1[0:3]这样,就可以获取到了abc这个字符串。同样我们可以查询出所有的数据,然后通过切片的方法只获取到第几条到第几条数据,这样的话就可以显示出部分的数据了。

    我们定义一下,每页显示5条数据,那么使用orm显示第一页的数据就应该是:TeacherTest.objects.all()[0:5]。根据这个规律展开以下分析:

    显示数据      页数  切片  切片分析

    第1条-第5条数据       1     [0:5]          [(1-1)*5:1*5]

    第6条-第10条数据     2          [5:10]        [(2-1)*5:2*5]

    第11条-第15条数据   3          [10:15]      [(3-1)*5:3*5]

    ......

    第m条-第n条数据         j          [m-1:n]    [(j-1)*5:j*5]

    通过上面的分析,我们知道了页数与显示数据的切片的关系了,那么我们就可以解决了一个显示的问题。

    orm显示数据的语句就是:TeacherTest.objects.all()[(页码-1)*5:页码*5]

    点击页码按钮通过url传递参数,后端获取传递的页码数就可以显示对应的数据了。

    3.通过上面分析已经解决了显示问题,那么接下来就要显示分页了。要想知道分页,首先要知道的就是有多少条数据,然后根据计算这些数据需要多少页来显示数据。

    获取总数据量:TeacherTest.objects.count()

    假设表中的数据量是26条数据,那么可以分6页,最后一页显示1条数据;数据量是27条,也是分6页,最后一页显示2条数据。所有我们可以先计算出每页显示5条数据的页数,然后再计算是否还有不足5条数据,如果还有不足5条数据需要显示,那么就再计算出每页显示5条数据的页数加上1页,就得出总页数了。

    伪代码如下:

    data_count=Teacher.objects.count()
    # 满足每页5条数据的页数
    page_five=data_count//5
    # 计算是否有余数
    page=data_count%5
    
    if page==0:
        # 总页数
        page_num=page_five
    else:
        # 总页数
        page_num=page_five+1

    也可以使用divmod(a,b)函数来计算页数,如果不了解这个内置函数的话,可以通过网上查询来获悉这个函数的用法。

    最后我们计算出了页码总数,就需要在前端显示分页的页码,通过我们点击给前端传递参数。如果将页数传递到前端的话,前端没有range可以让我们使用来遍历,显示每个页码,我们只能在后端做好后,将页码传递到前端。这里我使用的是html在后端拼接,然后传递到前端。下面可以参考具体的代码来学习:

    后端代码:

    def show_page(request):
        if request.method=="GET":
            current_page=request.GET.get("page") # 获取跳转的页数
            current_page=int(current_page)
            show_num=5 # 显示条数
            """
            1-5条  [0:5]     1  [(1-1)*5:1*5]
            6-10条 [5:10]    2  [(2-1)*5:2*5]
            11-15条[10:15]   3  [(3-1)*5:3*5]
            m-n条  [m-1:n]   h  [(m-1)*5:n*5]
            """
            start_data=(current_page-1)*show_num # 从第几条数据显示
            end_data=current_page*show_num           # 显示到第几条技术
    
            """
            显示页数
            """
            data_count=models.TeacherTest.objects.count() # 数据的总数量
            m,n=divmod(data_count,show_num)
    
           
            page_list=[]
            if n==0:
                page_count=m
                for p in range(1,page_count+1):
                    page='<li><a href="/app05/page/?page={0}">{0}</a></li>'.format(p)
                    page_list.append(page)
            else:
                page_count=m+1
                for p in range(1,page_count+1):
                    page = '<li><a href="/app05/page/?page={0}">{0}</a></li>'.format(p)
                    page_list.append(page)
    
            show_data=models.TeacherTest.objects.all()[start_data:end_data]
            return render(request,"page.html",{"allteacher":show_data,"pagecount":page_count,"page_list":page_list})

    前端代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- Optional theme -->
        <link rel="stylesheet" href="/static/css/bootstrap.min.css">
    </head>
    <body>
    <table class="table-bordered" border="1" width="300">
        {% for teacher in allteacher %}
            <tr>
            <td>{{ teacher.id }}</td>
            <td>{{ teacher.name }}</td>
            </tr>
        {% endfor %}
        
    </table>
    <nav aria-label="Page navigation">
      <ul class="pagination">
        <li>
          <a href="#" aria-label="Previous">
            <span aria-hidden="true">&laquo;</span>
          </a>
        </li>
          {% for page in page_list %}
              {{ page|safe }}
          {% endfor %}
        <li>
          <a href="#" aria-label="Next">
            <span aria-hidden="true">&raquo;</span>
          </a>
        </li>
      </ul>
    </nav>
    </body>
    </html>

    ==============================================================================================================

    此时分页就基本上写完了,但是我们在使用的时候会发现一个问题,就是如果有300条数据的时候,页数就会有60页,此时分页的页码就会全部显示到界面上,那样的话就显示不好看了。所以就要显示分页的长度了。

    以下代码就是更新后的代码

    def show_page(request):
        if request.method=="GET":
            current_page=request.GET.get("page") # 获取跳转的页数
            current_page=int(current_page)
            show_num=5 # 显示条数
            """
            1-5条  [0:5]     1  [(1-1)*5:1*5]
            6-10条 [5:10]    2  [(2-1)*5:2*5]
            11-15条[10:15]   3  [(3-1)*5:3*5]
            m-n条  [m-1:n]   h  [(m-1)*5:n*5]
            """
            start_data=(current_page-1)*show_num # 从第几条数据显示
            end_data=current_page*show_num       # 显示到第几条技术
    
            """
            显示页数
            """
            data_count=models.TeacherTest.objects.count() # 数据的总数量
            page_count,n=divmod(data_count,show_num)
            if n:
                page_count+=1
    
            # 总共展示11页
            max_page=5
            half_max_page=max_page//2
            # 页面上展示的页码从哪开始
            page_start=current_page-half_max_page
            # 页面上展示的页码到哪结束
            page_end=current_page+half_max_page
            # 如果当前页加上一半比总页码数还大
            if page_end>page_count:
                page_end=page_count
                page_start=page_count-max_page
            # 如果当前页减去一半,比1还小
            if page_start<=1:
                page_start=1
                page_end=max_page
    
            page_list=[]
            for p in range(page_start,page_end+1):
                page='<li><a href="/app05/page/?page={0}">{0}</a></li>'.format(p)
                page_list.append(page)
    
            show_data=models.TeacherTest.objects.all()[start_data:end_data]
            return render(request,"page.html",{"allteacher":show_data,"pagecount":page_count,"page_list":page_list})
  • 相关阅读:
    JavaScript中{}+{}
    网站性能优化
    C++是如何从代码到游戏的?
    C++是如何从代码到游戏的?
    【力扣】至少是其他数字两倍的最大数 中速题解
    代码编辑器选择Atom还是VScode?
    TIOBE 4 月榜单:少儿编程语言 Scratch 进入 TOP 20
    熟悉一下oncontextmenu事件的知识
    input属性type为file打开文件资源管理器时,如何限制多次选取或只能一次选取的行为
    HTML5的拖放事件
  • 原文地址:https://www.cnblogs.com/fjiqiang/p/10946001.html
Copyright © 2011-2022 走看看