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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM