1. 程式人生 > 實用技巧 >Django之分頁

Django之分頁

1. Django的內建分頁

1.1 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('p')

    paginator = Paginator(L, 10)
    # 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, 'index.html', {'
posts': posts})

1.2 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 }}">Previous</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 }}">Next</a>
          {% endif %}
      </span>
</div>
</body>
</html>

2. 擴充套件Django內建分頁

2.1 views.py

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

class CustomPaginator(Paginator):
    def __init__(self, current_page, max_pager_num, *args, **kwargs):
        self.current_page = int(current_page)
        self.max_pager_num = max_pager_num
        super(CustomPaginator, self).__init__(*args, **kwargs)

    def page_num_range(self):
        # 當前頁面
        # self.current_page
        # 總頁數
        # self.num_pages
        # 最多顯示的頁碼個數
        # self.max_pager_num
        print(1)
        if self.num_pages < self.max_pager_num:
            return range(1, self.num_pages + 1)
        print(2)
        part = int(self.max_pager_num / 2)
        if self.current_page - part < 1:
            return range(1, self.max_pager_num + 1)
        print(3)
        if self.current_page + part > self.num_pages:
            return range(self.num_pages + 1 - self.max_pager_num, self.num_pages + 1)
        print(4)
        return range(self.current_page - part, self.current_page + part + 1)

L = []
for i in range(999):
    L.append(i)

def index(request):
    current_page = request.GET.get('p')
    paginator = CustomPaginator(current_page, 11, L, 10)
    # 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, 'index.html', {'posts': posts})

2.2 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 }}">Previous</a>
    {% endif %}

    {% for i in posts.paginator.page_num_range %}
        <a href="?p={{ i }}">{{ i }}</a>
    {% endfor %}

    {% if posts.has_next %}
        <a href="?p={{ posts.next_page_number }}">Next</a>
    {% endif %}
</span>
</div>
</body>
</html>

3. 自定義分頁

3.1 自定義分頁外掛

pager.py

class Paginator(object):
    def __init__(self, totalCount, currentPage, perPageItemNum=10, maxPageNum=11):
        """
        totalCount:資料總個數
        currentPage:當前頁
        perPageItemNum: 每頁顯示的行數
        maxPageNum:最多顯示的頁碼個數
        """
        self.total_count = totalCount
        try:
            v = int(currentPage)
            if v <= 0:
                v = 1
            self.current_page = v
        except Exception as e:
            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):
        """總的頁數"""
        a, b = divmod(self.total_count, self.per_page_item_num)
        if b == 0:
            return a
        return a + 1

    def page_num_range(self):
        """頁碼範圍"""
        part = int(self.max_page_num / 2)
        # 總的頁數少於預設要顯示的頁碼數
        if self.num_pages < self.max_page_num:
            return range(1, self.num_pages + 1)
        # 當前頁碼處於第一頁的前一半位置
        if self.current_page - part < 1:
            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='?p=1'>首頁</a></li>"
        page_list.append(first)
        if self.current_page == 1:
            the_prev = "<li><a href='#'>上一頁</a></li>"
        else:
            the_prev = "<li><a href='?p=%s'>上一頁</a></li>" % (self.current_page - 1, )
        page_list.append(the_prev)

        # 生成中間所有頁的頁碼
        for i in self.page_num_range():
            if i == self.current_page:
                temp = "<li class='active'><a href='?p=%s'>%s</a></li>" % (i, i, )
            else:
                temp = "<li><a href='?p=%s'>%s</a></li>" % (i, i, )
            page_list.append(temp)

        # 生成下一頁和尾頁的頁碼
        if self.current_page == self.num_pages:
            the_next = "<li><a href='#'>下一頁</a></li>"
        else:
            the_next = "<li><a href='?p=%s'>下一頁</a></li>" % (self.current_page + 1, )
        page_list.append(the_next)
        last = "<li><a href='?p=%s'>尾頁</a></li>" % (self.num_pages, )
        page_list.append(last)

        # 列表容器中的各個頁碼轉換為字串
        result = ''.join(page_list)
        return result

3.2 在後臺函數中呼叫自定義分頁外掛

views.py

user_list = []
for i in range(1, 999):
    temp = {'username': 'root' + str(i), 'age': i, }
    user_list.append(temp)
    
def index(request):
    # 獲取當前頁碼號
    current_page = int(request.GET.get('p'))
    # 匯入自定義分頁外掛
    from app01.pager import Paginator
    # 引數依次為: 資料總個數, 當前頁碼號, 每頁顯示的行數, 最多顯示的頁碼個數
    # 後兩個引數預設為: 10, 11
    obj = Paginator(999, current_page,)
    # obj物件中可呼叫的屬性(方法):
    #     start       當前頁的起始條目索引
    #     end         當前頁的結束條目索引
    #     page_str()  生成的所有頁碼結構和樣式
    data_list = user_list[obj.start:obj.end]
    return render(request, 'index.html', {'data': data_list, 'page_obj': obj, })

3.3 模板檔案index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
</head>
<body>
        {# 資料內容 #}
        <ul>
            {% for row in data %}
                <li>{{ row.username }} -- {{ row.age }}</li>
            {% endfor %}
        </ul>

        {# 分頁的內容 #}
        <ul class="pagination">
            {{ page_obj.page_str|safe }}
        </ul>
</body>
</html>