Django 自定義分頁器

分頁推導

首先咱們須要明確的時候,get請求也是能夠攜帶參數的,因此咱們在朝後端發送查看數據的同時能夠攜帶一個參數告訴後端咱們想看第幾頁的數據html

其次咱們還須要知道一個點,queryset對象是支持索引取值和切片操做的,可是不支持負數索引狀況前端

接下來咱們就能夠推導咱們的自定義分頁器步驟了數據庫

current_page = request.GET.get("page",1)  # 獲取用戶想訪問的頁碼  若是沒有 默認展現第一頁
try:  # 因爲後端接受到的前端數據是字符串類型因此咱們這裏作類型轉換處理加異常捕獲
  current_page = int(current_page)
except Exception as e:
  current_page = 1
# 還須要定義頁面到底展現幾條數據
per_page_num = 10  # 一頁展現10條數據

# 須要對總數據進行切片操做 須要肯定切片起始位置和終止位置
start_page = ? 
end_page = ?
"""
下面須要研究current_page、per_page_num、start_page、end_page四個參數之間的數據關係
per_page_num = 10
current_page                start_page                  end_page
    1                           0                           10
    2                           10                          20
    3                           20                          30  
    4                           30                          40

per_page_num = 5
current_page                start_page                  end_page
    1                           0                           5
    2                           5                           10
    3                           10                          15  
    4                           15                          20
能夠很明顯的看出規律
start_page = (current_page - 1) * per_page_num
end_page =  current_page* per_page_num
"""

數據總頁面獲取

當我問你下面幾個問題的時候,你的心裏確定是鄙視的,不信的話那就請聽題bootstrap

問題1:總數據有100條,每頁展現10條,總共須要幾頁?後端

答案:10條app

問題2:總數據有101條,每頁展現10條,總共須要幾頁?框架

答案:11條spa

問題3:如何經過代碼算出到底須要多少條?code

答案:去你妹的,不會!!!htm

內置方法之divmod

>>> divmod(100,10)
(10, 0)  # 10頁
>>> divmod(101,10)
(10, 1)  # 11頁
>>> divmod(99,10)
(9, 9)  # 10頁
# 餘數只要不是0就須要在第一個數字上加一

咱們能夠判斷元祖的第二個數字是否爲0從而肯定到底須要多少頁來展現數據

book_queryset = models.Book.objects.all()
all_count = book_queryset.count()  # 數據總條數
all_pager, more = divmod(all_count, per_page_num)
if more:  # 有餘數則總頁數加一
  all_pager += 1

至此分頁器大體的功能及思路咱們就已經大體清楚了

最後咱們只須要利用start_page和end_page對總數據進行切片取值再傳入前端頁面就可以實現分頁展現

book_list = models.Book.objects.all()[start_page:end_page]
return render(request,'booklist.html',locals())

接下來就是前端頁面的代碼編寫了

{% for book in book_list %}
    <p>{{ book.title }}</p>
{% endfor %}

如今咱們實現了最簡單的分頁,可是前端沒有按鈕去讓用戶點擊須要看第幾頁,因此咱們須要渲染分頁器相關代碼,這裏咱們不作要求直接去bootstrap框架拷貝代碼便可

終極大法

上面是自定義分頁器開發流程的基本思路,咱們不須要掌握代碼的編寫,只須要掌握基本用法便可

自定義分頁器封裝代碼

class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封裝分頁相關數據
        :param current_page: 當前頁
        :param all_count:    數據庫中的數據總條數
        :param per_page_num: 每頁顯示的數據條數
        :param pager_count:  最多顯示的頁碼個數
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        if current_page < 1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

        # 總頁碼
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager

        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        # 若是總頁碼 < 11個:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 總頁碼  > 11
        else:
            # 當前頁若是<=頁面上最多顯示11/2個頁碼
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 當前頁大於5
            else:
                # 頁碼翻到最後
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        # 添加前面的nav和ul標籤
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">首頁</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一頁</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一頁</a></li>' % (self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一頁</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一頁</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">尾頁</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加標籤
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)

自定義分頁器的使用

後端

 def get_book(request):
   book_list = models.Book.objects.all()
   current_page = request.GET.get("page",1)
   all_count = book_list.count()
   #獲得一個分頁器類的對象
   page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
   #針對真實的queryset數據進行切片操做
   page_queryset = book_list[page_obj.start:page_obj.end]
   return render(request,'booklist.html',locals())

前端

<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            {% for book in page_queryset %}
            <p>{{ book.title }}</p>
            {% endfor %}
            {{ page_obj.page_html|safe }}
        </div>
    </div>
</div>
相關文章
相關標籤/搜索