簡單的分頁器實現


簡單的分頁功能

urls.py

urlpatterns = [
    url(r'^page/', views.page,name='page'),
]

views.py

users = [{"name": f"alex{i}", "pwd": "dsb"} for i in range(1, 355)]

def page(request):
    user_list = users
    try:
        page = int(request.GET.get('page', 1))
        if page <= 0:
            page = 1
    except Exception:
        page = 1

    """
    索引切片
    page   起始   終止
    1       0     10
    2       10    20
    3       20    30
    """
    # 每頁展示的數據
    per_num = 10
    # 數據切片起始值
    start = (page - 1) * per_num
    # 數據切片終止值
    end = page * per_num
    # 總數據條數
    page_count = len(user_list)
    # 總頁碼數
    sum_page, more = divmod(page_count, per_num)
    if more:
        sum_page += 1
    # 前端循環的a標簽的值
    num = [i for i in range(1, sum_page + 1)]
    user_list = user_list[start:end]
    return render(request, 'page.html', locals())

html.py(bootstrap樣式中的分頁組件)

   <div class="form-group col-sm-7">
        <table class="table table-hover table-bordered">
            <thead>
            <tr>
                <th>name</th>
                <th>pwd</th>
            </tr>
            </thead>
            <tbody>
            {% for user in user_list %}
                <tr>
                    <td>{{ user.name }}</td>
                    <td>{{ user.pwd }}</td>
                </tr>
            {% endfor %}
            </tbody>
        </table>
    </div>

    <div class="pull-left form-group col-sm-7">
        <nav aria-label="Page navigation">
            <ul class="pagination">
                <li>
                    <a href="#" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                    </a>
                </li>
                {% for n in num %}
                    <li><a href="{% url 'page' %}?page={{ n }}">{{ n }}</a></li>
                {% endfor %}
                <li>
                    <a href="#" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                    </a>
                </li>
            </ul>
        </nav>
    </div>

效果:簡單的分頁完成

 上面功能中展示了數據的所有的頁碼,接下來我們將會對頁碼的展示進行升級,如:每頁展示十個頁碼

頁碼數量限制

url與html文件不變

views.py

users = [{"name": f"alex{i}", "pwd": "dsb"} for i in range(1, 301)]

def page(request):
    user_list = users
    try:
        page = int(request.GET.get('page', 1))
        if page <= 0:
            page = 1
    except Exception:
        page = 1

    """
    索引切片
    page   起始   終止
    1       0     10
    2       10    20
    3       20    30
    """
    # 每頁展示的數據
    per_num = 10
    # 數據切片起始值
    start = (page - 1) * per_num
    # 數據切片終止值
    end = page * per_num
    # 總數據條數
    page_count = len(user_list)
    # 總頁碼數
    sum_page, more = divmod(page_count, per_num)
    if more:
        sum_page += 1
    # 前端循環的a標簽的值
    num = [i for i in range(1, sum_page + 1)]

    # 頁碼限制
    # 頁面最大顯示頁碼
    max_show = 10
    # 頁碼的切片的起始值
    page_start = 0
    # 頁碼切片的終止值
    page_end = max_show
    # 頁碼的偏移量
    half_page = max_show // 2
    if page < max_show:
        """
        如果page在第一頁,什么都不做,即page_start=0,page_end=max_show
        """
        pass
    if page > sum_page:
        """
        如果page參數大於總頁碼數,跳轉到最后一頁,針對於url上面手動輸入page參數
        """
        # 終止值為最后一頁
        page_end = sum_page
        # 起始值向前便宜half_page
        page_start = page_end - half_page
        # 數據部分也需要設定,不然顯示為空
        start = (sum_page - 1) * per_num
        end = sum_page * per_num
    else:
        """
        page當前頁碼即不在第一頁,也不在最后一頁(或超過最后一頁),起始值向前偏移half_page,向后偏移half_page
        """
        page_start = page - half_page
        page_end = page + half_page
    
    # 當總頁碼數小於每頁最大展示頁碼數量時,無論在那一頁都展示全部的頁碼(針對數據少,page處於max_show與sum_page之間時的bug)
    if sum_page < max_show:
        page_start = 0
        page_end = sum_page
        
    num = num[page_start:page_end]
    user_list = user_list[start:end]
    return render(request, 'page.html', locals())

當前頁選中

bootstrap中active類選擇器是激活的樣式,在前端判斷后台接收到的page登不等於前端的頁碼,等於則添加激活樣式。

html文件

......
 <div class="pull-left form-group col-sm-7">
        <nav aria-label="Page navigation">
            <ul class="pagination">
                <li>
                    <a href="#" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                    </a>
                </li>
                {% for n in num %}
                    <li class="{% if page == n %}active{% endif %}"><a href="{% url 'page' %}?page={{ n }}">{{ n }}</a>  {# 主要操作在這里#}
                    </li>
                {% endfor %}
                <li>
                    <a href="#" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                    </a>
                </li>
            </ul>
        </nav>
    </div>
......

正常情況下,激活樣式是完成的,但這里有個bug就是當手動在url地址中輸入大於總頁碼的page時就沒有激活樣式了,所以,我們需要在views文件中針對性的將page修改一下,如下:

......
    if page > sum_page:
        """
        如果page參數大於總頁數,跳轉到最后一頁,針對於url上面手動輸入page參數
        """
        # 終止值為最后一頁
        page_end = sum_page
        # 起始值向前便宜half_page
        page_start = page_end - half_page
        # 數據部分也需要設定,不然顯示為空
        start = (sum_page - 1) * per_num
        end = sum_page * per_num
        # 當page大於總頁碼時,讓page等於最大的頁碼,為了給最后一頁添加激活樣式  # 主要操作在這里,原理是:因為當用戶手動輸入的頁碼大於總頁碼時,后台獲取的數據與前端的必然不同,因此,我們在這里手動將page設置為總頁碼,即可。
        page = sum_page
......

效果如圖:

 激活樣式添加完成

后台進行頁碼樣式的編寫及上下頁設置

這里主要在后台生成html代碼(頁碼相關的html代碼,包括樣式的激活,上下頁等,都在后台生成,前端只需要調用即可)

views.py

# -*- coding: utf-8 -*-
# __author__ = "maple"


users = [{"name": f"alex{i}", "pwd": "dsb"} for i in range(1, 301)]

def page(request):
    user_list = users
    try:
        page = int(request.GET.get('page', 1))
        if page <= 0:
            page = 1
    except Exception:
        page = 1

    """
    索引切片
    page   起始   終止
      0     10
      10    20
      20    30
    """
    # 每頁展示的數據
    per_num = 3
    # 數據切片起始值
    start = (page - 1) * per_num
    # 數據切片終止值
    end = page * per_num
    # 總數據條數
    page_count = len(user_list)
    # 總頁碼數
    sum_page, more = divmod(page_count, per_num)
    if more:
        sum_page += 1
    # 前端循環的a標簽的值
    num = [i for i in range(1, sum_page + 1)]

    # 頁碼限制
    # 頁面最大顯示頁碼
    max_show = 6
    # 頁碼的切片的起始值
    page_start = 0
    # 頁碼切片的終止值
    page_end = max_show
    # 頁碼的偏移量
    half_page = max_show // 2

    if page < max_show:
        """
        如果page在第一頁,什么都不做,即page_start=0,page_end=max_show
        """
        pass
    if page > sum_page:
        """
        如果page參數大於總頁碼數,跳轉到最后一頁,針對於url上面手動輸入page參數
        """
        # 終止值為最后一頁
        page_end = sum_page
        # 起始值向前偏移half_page
        page_start = page_end - half_page
        # 數據部分也需要設定,不然顯示為空
        start = (sum_page - 1) * per_num
        end = sum_page * per_num
        # 當page大於總頁碼時,讓page等於最大的頁碼,為了給最后一頁添加激活樣式
        page = sum_page
    else:
        """
        page當前頁碼即不在第一頁,也不在最后一頁(或超過最后一頁),起始值向前偏移half_page,向后偏移half_page
        """
        page_start = page - half_page
        page_end = page + half_page

    # 當總頁碼數小於每頁最大展示頁碼數量時,無論在那一頁都展示全部的頁碼(針對數據少,page處於max_show與sum_page之間時的bug)
    if sum_page < max_show:
        page_start = 0
        page_end = sum_page

    num = num[page_start:page_end]

    html_list = []
    # 頁碼樣式的頭
    html_list.append(
        '<div class="pull-left form-group col-sm-7"><nav aria-label="Page navigation"><ul class="pagination">')
    # 當當前頁為1時,添加上一頁禁用樣式disabled
    if page == 1:
        html_list.append(
            '<li class="disabled"><a aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>')
    else:
        html_list.append(
            '<li ><a href="?page={}" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>'.format(
                page - 1))

    for n in num:
        if page == n:
            html_list.append('<li class="active"><a>{}</a></li>'.format(n))
        else:
            html_list.append('<li><a href="?page={}">{}</a></li>'.format(n, n))

    # 當前頁為最后一頁時,添加下一頁禁用樣式disabled
    if page == sum_page:
        html_list.append(
            '<li class="disabled"><a  aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>')
    else:
        html_list.append(
            '<li><a href="?page={}" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>'.format(
                page + 1))

    # 頁碼樣式的尾
    html_list.append('</ul></nav></div>')

    # 將列表中的html代碼拼接起來
    html_list = "".join(html_list)

    user_list = user_list[start:end]
    return render(request, 'page.html', locals())
 
View Code

html.py(附帶所有的關於關於頁碼的樣式)

 {{ html_list|safe }}

小工具:跳轉

html頁面

    {{ html_list|safe }}
 # form表單不寫method默認為get請求,且get請求會將input提交的值以url參數的形式保存並提交到后台
    <form action="">
        <input type="text" name="page">
        <button>跳轉</button>
    </form>

至此,簡單的分頁功能就已經完成了,但我們以后開發項目必然要用到分頁功能,我們要如何使用自己開發的分頁功能呢?在寫一遍?不,我們將它封裝成類,在使用的時候進行調用即可。

封裝成類

class Pagination(object):
    def __init__(self, page, page_count, per_num=10, max_show=10):
        """
        :param page:前端傳入的頁碼
        :param page_count: 分頁的數據總條數
        :param per_num: 每頁顯示的數據條數
        :param max_show: 每頁顯示的最大頁碼數
        """
        self.page = page
        self.page_count = page_count
        self.per_num = per_num
        self.max_show = max_show

        try:
            self.page = int(self.page)
            if self.page <= 0:
                self.page = 1
        except Exception:
            self.page = 1

        """
        索引切片
        page   起始   終止
      0     10
      10    20
      20    30
        """
        # 數據切片起始值
        self.start = (self.page - 1) * self.per_num
        # 數據切片終止值
        self.end = self.page * self.per_num
        # 總頁碼數
        self.sum_page, more = divmod(self.page_count, self.per_num)
        if more:
            self.sum_page += 1
        # 前端循環的a標簽的值
        self.num = [i for i in range(1, self.sum_page + 1)]

        # 頁碼限制
        # 頁碼的切片的起始值
        self.page_start = 0
        # 頁碼切片的終止值
        self.page_end = self.max_show
        # 頁碼的偏移量
        half_page = self.max_show // 2

        if self.page < self.max_show:
            """
            如果page在第一頁,什么都不做,即page_start=0,page_end=max_show
            """
            pass

        if self.page > self.sum_page:
            """
            如果page參數大於總頁碼數,跳轉到最后一頁,針對於url上面手動輸入page參數
            """
            # 終止值為最后一頁
            self.page_end = self.sum_page
            # 起始值向前偏移half_page
            self.page_start = self.page_end - half_page
            # 數據部分也需要設定,不然顯示為空
            self.start = (self.sum_page - 1) * self.per_num
            self.end = self.sum_page * self.per_num
            # 當page大於總頁碼時,讓page等於最大的頁碼,為了給最后一頁添加激活樣式
            self.page = self.sum_page

        else:
            """
            page當前頁碼即不在第一頁,也不在最后一頁(或超過最后一頁),起始值向前偏移half_page,向后偏移half_page
            """
            self.page_start = self.page - half_page
            self.page_end = self.page + half_page

        # 當總頁碼數小於每頁最大展示頁碼數量時,無論在那一頁都展示全部的頁碼
        if self.max_show > self.sum_page:
            self.page_start = 0
            self.page_end = self.sum_page
        # 當傳入的總數據量小於等於0時(主要是等於零),會報錯,通過下面的判斷來解決這個問題
        if page_count <= 0:
            self.start = 0
            self.end = 0

    def page_html(self):
        num = self.num[self.page_start:self.page_end]
        html_list = []
        # 頁碼樣式的頭
        html_list.append(
            '<div class="pull-left form-group col-sm-7" style="padding-left:0"><nav  aria-label="Page navigation"><ul class="pagination">')
        # 當前頁為1時,添加上一頁禁用樣式disabled
        if self.page == 1:
            html_list.append(
                '<li class="disabled"><a aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>')
        else:
            html_list.append(
                '<li ><a href="?page={}" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>'.format(
                    self.page - 1))
        for n in num:
            if self.page == n:
                html_list.append('<li class="active"><a>{}</a></li>'.format(n))
            else:
                html_list.append('<li><a href="?page={}">{}</a></li>'.format(n, n))

        # 當前頁為最后一頁時,添加下一頁禁用樣式disabled
        if self.page == self.sum_page:
            html_list.append(
                '<li class="disabled"><a aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>')
        else:
            html_list.append(
                '<li><a href="?page={}" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>'.format(
                    self.page + 1))
        # 頁碼樣式的尾
        html_list.append('</ul></nav></div>')
        # 將列表中的html代碼拼接起來
        html_list = "".join(html_list)
        return html_list
View Code

使用自定義分頁器類

views.py

users = [{"name": f"alex{i}", "pwd": "dsb"} for i in range(1, 355)]

from utils import pagination
def page(request):
    user_list = users
    page = request.GET.get('page')
    pat_obj = pagination.Pagination(page, len(user_list)) # 實例化一個分頁器對象
    user_list = user_list[pat_obj.start:pat_obj.end] # 進行數據的切片操作
    return render(request, 'page.html', locals())

page.html

    <div class="form-group col-sm-7">
        <table class="table table-hover table-bordered">
            <thead>
            <tr>
                <th>name</th>
                <th>pwd</th>
            </tr>
            </thead>
            <tbody>
            {% for user in user_list %}
                <tr>
                    <td>{{ user.name }}</td>
                    <td>{{ user.pwd }}</td>
                </tr>
            {% endfor %}
            </tbody>
        </table>
    </div>
    {{ pat_obj.page_html|safe }}  {# 通過分頁器對象調用page_html方法 #}

注:分頁器中引入的是bootstrap框架的樣式,使用前需先在模板中引入bootstrap

分頁器終極版

分頁器:

# -*- coding: utf-8 -*-
# __author__ = "maple"
from django.http.request import QueryDict


class Pagination(object):
    def __init__(self, page, page_count, qd=None, per_num=10, max_show=10):
        """
        :param page:前端傳入的頁碼
        :param page_count: 分頁的數據總條數
        :param per_num: 每頁顯示的數據條數
        :param max_show: 每頁顯示的最大頁碼數
        """
        self.page = page
        self.page_count = page_count
        self.per_num = per_num
        self.max_show = max_show
        self.qd = qd
        if not qd:
            qd = QueryDict(mutable=True)
            self.qd = qd

        try:
            self.page = int(self.page)
            if self.page <= 0:
                self.page = 1
        except Exception:
            self.page = 1

        """
        索引切片
        page   起始   終止
        1       0     10
        2       10    20
        3       20    30
        """
        # 數據切片起始值
        self.start = (self.page - 1) * self.per_num
        # 數據切片終止值
        self.end = self.page * self.per_num
        # 總頁碼數
        self.sum_page, more = divmod(self.page_count, self.per_num)
        if more:
            self.sum_page += 1
        # 前端循環的a標簽的值
        self.num = [i for i in range(1, self.sum_page + 1)]

        # 頁碼限制
        # 頁碼的切片的起始值
        self.page_start = 0
        # 頁碼切片的終止值
        self.page_end = self.max_show
        # 頁碼的偏移量
        half_page = self.max_show // 2

        if self.page < self.max_show:
            """
            如果page在第一頁,什么都不做,即page_start=0,page_end=max_show
            """
            pass

        if self.page > self.sum_page:
            """
            如果page參數大於總頁碼數,跳轉到最后一頁,針對於url上面手動輸入page參數
            """
            # 終止值為最后一頁
            self.page_end = self.sum_page
            # 起始值向前偏移half_page
            self.page_start = self.page_end - half_page
            # 數據部分也需要設定,不然顯示為空
            self.start = (self.sum_page - 1) * self.per_num
            self.end = self.sum_page * self.per_num
            # 當page大於總頁碼時,讓page等於最大的頁碼,為了給最后一頁添加激活樣式
            self.page = self.sum_page

        else:
            """
            page當前頁碼即不在第一頁,也不在最后一頁(或超過最后一頁),起始值向前偏移half_page,向后偏移half_page
            """
            self.page_start = self.page - half_page
            self.page_end = self.page + half_page

        # 當總頁碼數小於每頁最大展示頁碼數量時,無論在那一頁都展示全部的頁碼
        if self.max_show > self.sum_page:
            self.page_start = 0
            self.page_end = self.sum_page
        # 當傳入的總數據量小於等於0時(主要是等於零),會報錯,通過下面的判斷來解決這個問題
        if page_count <= 0:
            self.start = 0
            self.end = 0

    def page_html(self):
        num = self.num[self.page_start:self.page_end]
        html_list = []
        # 頁碼樣式的頭
        html_list.append(
            '<div class="pull-left form-group col-sm-7" style="padding-left:0"><nav  aria-label="Page navigation"><ul class="pagination">')
        # 當前頁為1時,添加上一頁禁用樣式disabled
        if self.page == 1:
            self.qd['page'] = 1
            html_list.append(
                '<li class="disabled"><a href="?{}" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>'.format(
                    self.qd.urlencode()))
        else:
            self.qd['page'] = self.page -1
            html_list.append(
                '<li ><a href="?{}" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>'.format(
                    self.qd.urlencode()))
        for n in num:
            self.qd['page'] = n
            if self.page == n:
                html_list.append('<li class="active"><a>{}</a></li>'.format(n))
            else:
                html_list.append('<li><a href="?{}">{}</a></li>'.format(self.qd.urlencode(), n))

        # 當前頁為最后一頁時,添加下一頁禁用樣式disabled
        if self.page == self.sum_page:
            self.qd['page'] = self.sum_page
            html_list.append(
                '<li class="disabled"><a href="?{}" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>'.format(
                    self.qd.urlencode()))
        else:
            self.qd['page'] = self.page + 1
            html_list.append(
                '<li><a href="?{}" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>'.format(
                    self.qd.urlencode()))
        # 頁碼樣式的尾
        html_list.append('</ul></nav></div>')
        # 將列表中的html代碼拼接起來
        html_list = "".join(html_list)
        return html_list
View Code

使用:

from utils import pagination # 導入自定義分頁器
page = request.GET.get('page', 1) #獲取當前頁碼參數
pag_obj = pagination.Pagination(page=page, page_count=customer_obj.count(),qd=request.GET.copy(), per_num=3, max_show=10) #實例化分頁器對象
customer_obj = customer_obj[pag_obj.start:pag_obj.end] # 對queryset對象進行分頁

 


免責聲明!

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



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