天天看點

Django分頁器

Django分頁器

一、分頁器簡介

當資料量非常大時, 我們不可能把所有的資料都放在同一頁中, 于是就有了分頁的概念, 将資料像書一樣每一頁規定可容納多少條資料, 運用到Django中的分頁元件, 它其實是Django内置的一個類

二.Paginator對象與Page類對象

1.如何得到這兩個類對象

  • 導入分頁類
from django.core.paginator import Paginator
           
  • Paginator類對象
# 文法僞代碼
paginator = Paginator([要分頁的資料],[每頁顯示條數])
# 示例
paginator = Paginator(shop_list,10)
           
  • Page類對象
# 文法僞代碼
page = paginator.page([第幾頁])
# 示例
page = paginator.page(2)  # 擷取第二頁對象
           

2.Paginator類對象屬性和方法

  • 屬性
屬性名 說明
count 傳回資料總條數
num_pages 傳回分頁之後的總頁數
per_page 每頁顯示的條數
page_range 傳回分頁後頁碼的清單
  • 方法
方法名
page(self, number) 傳回地number頁的page類執行個體對象

3.Page類對象屬性和方法

number 傳回目前頁頁碼
object_list 傳回目前頁的資料清單
paginator 傳回對應的Paginator類對象
has_previous( ) 判斷目前頁是否有上一頁
has_next( ) 判斷目前頁是否有下一頁
previous_page_number( ) 傳回前一頁頁碼
next_page_number( ) 傳回下一頁頁碼

三.建立表并插入資料(準備工作)

1.建立模型類

class Shop(models.Model):
    name = models.CharField(max_length=64)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    nums = models.IntegerField(verbose_name='商品剩餘')

    def __str__(self):
        return self.name
           

2.使用for循環批量插入資料

for i in range(1,151):
    models.Shop.objects.create(name=f'商品{i}',price=10+int(f'{i}'),nums=f'{random.randint(1,15)}')
           
每循環一次就連接配接一次資料庫, 效率低

3.bulk_create( ) : 批量插入資料

import random
shop_list = []
for i in range(1,151):
    book = models.Shop(name=f'商品{i}',price=10+int(f'{i}'),nums=f'{random.randint(1,15)}')
    shop_list.append(book)
models.Shop.objects.bulk_create(shop_list,10)  # 第二個參數是每次插入的條數
           
可以指定每次插入的條數, 效率高

4.将初始資料渲染到頁面

  • page_shop.html 檔案
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-info">
                <div class="panel-heading text-center">商品資訊表</div>
                <div class="panel-body">
                    <table class="table table-striped table-hover">
                        <thead>
                            <tr>
                                <th>編号</th>
                                <th>商品名</th>
                                <th>價格</th>
                                <th>剩餘個數</th>
                            </tr>
                        </thead>
                        <tbody>
                            {% for obj in shop_obj %}
                                <tr>
                                    <th>{{ obj.id }}</th>
                                    <th>{{ obj.name }}</th>
                                    <th>{{ obj.price }}</th>
                                    <th>{{ obj.nums }}</th>
                                </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>         
           
  • 展示效果
Django分頁器
以上是沒有沒有分頁的效果, 一頁翻不到頭, 使用起來不友善

四.分頁器完整用法

1.實作需求

  • 每頁顯示15條資料
  • 頁碼清單隻展示11頁, 随着目前頁變化
  • 目前頁為第一頁則禁用’‘上一頁’'按鈕
  • 目前頁為最後頁則禁用’‘下一頁’'按鈕
  • 目前頁按鈕處于激活狀态

2.效果展示

  • 整體展示

3.代碼實作

  • 路由層 urls.py 檔案
re_path('^page_shop/', views.page_shop)
           
  • 視圖層 views.py 檔案
  • 分頁後的paginator對象,用來展示資料
  • 分頁後的頁碼清單,我們規定每次展示11個頁碼,中間頁碼為目前頁,左右頁碼随之變化(這裡需要注意前11頁和後11頁)
  • 收到前端點選的頁碼,我們要傳回該頁碼(page)對象(注意小于或超出中頁碼的情況)
from django.shortcuts import render, HttpResponse, redirect
from app01 import models

def page_shop(request):
    # ????1.分頁後的paginator對象
    current_page = int(request.GET.get('page_num',1))  # 擷取使用者點選的頁碼,沒有則預設第一頁
    shop_list = models.Shop.objects.all()              # 擷取所有的商品對象清單
    paginator = Paginator(shop_list,15)                # 每頁展示15條商品資訊

    # ????2.頁碼清單
    # 如果分頁後的總頁數大于11
    if paginator.num_pages > 11:
        # 總共11頁,取中間頁(目前頁)來判斷是否是第1~11頁
        if current_page - 5 < 1:
            # 1~11頁碼清單
            page_range = range(1, 12)
        # 取11頁的中間頁(目前頁)判斷是否是最後11頁
        elif current_page + 5 > paginator.num_pages:
            # 最後11頁頁碼清單
            page_range = range(paginator.num_pages - 10, paginator.num_pages + 1)
        else:
            # 如果不是前面11頁,也不是後面11頁,那麼頁碼清單動态就會随着目前清單動态加減
            page_range = range(current_page - 5, current_page + 5)
    else:
        # 總頁數小于11就直接全部顯示
        page_range = paginator.page_range

    # ????3.page對象
    try:
        # 如果前端傳過來的頁碼小于分頁後的最小頁碼或者大于最大頁碼就會報錯
        page = paginator.page(current_page)
    except Exception as E:
        current_page = 1  # 如果超出或小于我們就讓其預設展示第一頁
        page = paginator.page(current_page)

    return render(request, 'page.html', {'page_range': page_range, 'page': page, 'current_page': current_page})
           
  • 模闆層 page.html 檔案
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-info">
                <div class="panel-heading text-center">商品資訊表</div>
                <div class="panel-body">
                    <table class="table table-striped table-hover">
                        <thead>
                            <tr>
                                <th>編号</th>
                                <th>商品名</th>
                                <th>價格</th>
                                <th>剩餘個數</th>
                            </tr>
                        </thead>
                        <tbody>
                            {# 展示目前頁的所有資料 #}
                            {% for obj in page.object_list %}
                                <tr>
                                    <th>{{ obj.id }}</th>
                                    <th>{{ obj.name }}</th>
                                    <th>{{ obj.price }}</th>
                                    <th>{{ obj.nums }}</th>
                                </tr>
                            {% endfor %}
                        </tbody>
                    </table>
{# -------------------上面為資料渲染,下面為頁碼清單-------------------- #}                   
                    <div class="text-center">
                        <nav aria-label="Page navigation">
                            <ul class="pagination">
                                {# 判斷目前頁是否有上一頁(針對向左的箭頭按鈕) #}
                                {% if page.has_previous %}
                                    <li>
                                        {# 如果有上一頁就跳到上一頁 #}
                                        <a href="/page_shop/?page_num={{ page.previous_page_number }}"
                                           aria-label="Previous">
                                            <span aria-hidden="true">&laquo;</span>
                                        </a>
                                    </li>
                                {% else %}
                                    {# 如果沒有上一頁,就将該按鈕禁用 #}
                                    <li class="disabled">
                                        <a href="" aria-label="Previous">
                                            <span aria-hidden="true">&laquo;</span>
                                        </a>
                                    </li>
                                {% endif %}

                                {# 從頁碼清單中循環取出頁碼與目前頁做對比 #}
                                {% for foo in page_range %}
                                    {% if current_page == foo %}
                                        {# 如果是目前頁,就将目前頁按鈕變成激活狀态(藍色) #}
                                        <li class="active"><a href="/page_shop/?page_num={{ foo }}">{{ foo }}</a></li>
                                    {% else %}
                                        {# 如果不是則不變色 #}
                                        <li><a href="/page_shop/?page_num={{ foo }}">{{ foo }}</a></li>
                                    {% endif %}

                                {% endfor %}

                                {# 判斷但前頁是否有下一頁(針對向右的箭頭按鈕) #}
                                {% if page.has_next %}
                                    <li>
                                        {# 如果有則跳轉到下一頁 #}
                                        <a href="/page_shop/?page_num={{ page.next_page_number }}" aria-label="Next">
                                            <span aria-hidden="true">&raquo;</span>
                                        </a>
                                    </li>
                                {% else %}
                                    {# 沒有下一頁則将按鈕禁用 #}
                                    <li class="disabled">
                                        <a href="" aria-label="Next">
                                            <span aria-hidden="true">&raquo;</span>
                                        </a>
                                    </li>
                                {% endif %}

                            </ul>
                        </nav>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>