django 分頁組件

1、仿django分頁功能本身實現css

urls.pyhtml

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index.html$', views.index),

    ]

views.py前端

from django.shortcuts import render
from app01 import models

# Create your views here.


USER_LIST = []

#建立數據999條
for i in range(999):
    temp = {'name':'root'+str(i),'age':i }
    #加到userlist列表中
    USER_LIST.append(temp)

def index(request):
    #每頁顯示10條數據
    per_page_count = 10
    #current-page 當有頁
    current_page = request.GET.get('p')
    #數字運算要轉成int類型
    current_page = int(current_page)
    #若是是第1頁,索引0-9,就是1-10的數
    #p=1
    #0,10   0-9  取索引
    #p=2
    #大於等於10,小於20就是10-19
    #10,20 10-19
    #start 開始頁數  end=結束頁數

    #若是p=1-1=0
    start = (current_page - 1) * per_page_count
    #1 * 10=10
    end = current_page*per_page_count
    #數據切片,每次顯示10頁
    data = USER_LIST[start:end]

    #上一頁
    prev_pager = current_page -1
    #下一頁
    next_pager = current_page +1
    return render(request,'index.html',{'user_list':data,'prev_pager':prev_pager,'next_pager':next_pager })

index.html數據庫

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        {% for row in user_list %}
        <li>{{ row.name }}-{{ row.age }}</li>
        {% endfor %}
    </ul>
    <a href="/index.html?p={{ prev_pager }}">上一頁</a>
    <a href="/index.html?p={{ next_pager }}">下一頁</a>
</body>
</html>

 

2、利用django自帶分頁組件實現分頁功能django

使用分頁器Paginator:
在視圖中使用 Paginator來爲查詢集分頁。咱們提供視圖以及相關的模板來展現如何展現這些結果。bootstrap

Paginator經常使用屬性
per_page: 每頁顯示條目數量
count: 數據總個數
num_pages:總頁數
page_range:總頁數的索引範圍,頁碼的範圍,從1開始,例如[1, 2, 3, 4]。

Paginator所需參數:app

object_list 一個列表,元祖或則Django 的Queryset 對象 或則其餘對象帶有 count() or __len__()的方法
per_page :就是1頁顯示幾條數據 

Paginator對象的方法:
post

page(number) :返回在提供的下標處的Page對象,下標以1開始。

使用page對象方法:測試

Page.has_next()
若是有下一頁,則返回True。

Page.has_previous()
若是有上一頁,返回 True。

Page.has_other_pages()
若是有上一頁或下一頁,返回True。

Page.next_page_number()
返回下一頁的頁碼。若是下一頁不存在,拋出InvalidPage異常。

Page.previous_page_number()
返回上一頁的頁碼。若是上一頁不存在,拋出InvalidPage異常。

Page.start_index()
返回當前頁上的第一個對象,相對於分頁列表的全部對象的序號,從1開始。好比,將五個對象的列表分爲每頁兩個對象,第二頁的start_index()會返回3。

Page.end_index()
返回當前頁上的最後一個對象,相對於分頁列表的全部對象的序號,從1開始。 好比,將五個對象的列表分爲每頁兩個對象,第二頁的end_index() 會返回 4。

屬性網站

Page.object_list
當前頁上全部對象的列表。

Page.number
當前頁的序號,從1開始。

Page.paginator
相關的Paginator對象。

代碼示例:

 

Django內置分頁:Paginator、Page

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # url(r'^index.html$', views.index),
    url(r'^index1.html$', views.index1),
    ]

views.py

from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse

from app01 import models

# Create your views here.


USER_LIST = []

#建立數據999條
for i in range(999):
    temp = {'name':'root'+str(i),'age':i }
    #加到userlist列表中
    USER_LIST.append(temp)


def index1(request):
    from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
    #所有數據:USER_LIST,=>得出共有多少條數據
    # per_page: 每頁顯示條目數量
    # count:    數據總個數
    # num_pages:總頁數
    # page_range:總頁數的索引範圍,如: (1,10),(1,200)
    # page:     page對象 (是否具備下一頁,是否有上一頁)

    current_page = request.GET.get('p')
    #Paginator對象,裏面封裝了上面那些值,把USER_LIST對象傳過來了,顯示10頁
    paginator = Paginator(USER_LIST,10)
    try:
        #page對象
        #posts配置對象(current_page用戶可能填些不合法的字段)
        #paginator經過拿到了page對象,把current_page傳進來
        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,'index1.html' ,{'posts':posts})

index1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        {% for row in posts.object_list %}
            <li>{{ row.name }}-{{ row.age }}</li>
        {% endfor %}
    </ul>
   {% include 'include/pager.html' %}
</body>
</html>

pager.html

 {% if posts.has_previous %}
    <a href="/index1.html?p={{ posts.previous_page_number }}">上一頁</a>
    {% else %}
    <a href="#">上一頁</a>
{% endif %}

{% if posts.has_next %}
    <a href="/index1.html?p={{ posts.next_page_number }}">下一頁</a>
{% endif %}

<span>
    {{ posts.number }} / {{ posts.paginator.num_pages }}
</span>
{#切片完後,就叫object_list#}

 

3、擴展Django內置分頁

urls.py

from django.conf.urls import url
from django.contrib import admin
from  app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/$', views.listing),
]

views.py

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

# Create your views here.

#模擬測試網頁數據
USER_LIST = []
for i in range(1,999):
    temp = {"name":"root"+str(i),"age":i}
    USER_LIST.append(temp)


class CustomPaginator(Paginator):
    def __init__(self,current_page,per_pager_num,*args,**kwargs):
        # per_pager_num  顯示的頁碼數量
        self.current_page = int(current_page)
        self.per_pager_num = int(per_pager_num)
        super(CustomPaginator,self).__init__(*args,**kwargs)
    def pager_num_range(self):
        '''
        自定義顯示頁碼數
        第一種:總頁數小於顯示的頁碼數
        第二種:總頁數大於顯示頁數  根據當前頁作判斷  a 若是當前頁大於顯示頁一半的時候  ,往右移一下
                                                b 若是當前頁小於顯示頁的一半的時候,顯示當前的頁碼數量
        第三種:當前頁大於總頁數
        :return:
        '''
        if self.num_pages < self.per_pager_num:
            return range(1,self.num_pages+1)

        half_part = int(self.per_pager_num/2)
        if self.current_page <= half_part:
            return range(1,self.per_pager_num+1)

        if (self.current_page+half_part) > self.num_pages:
            return range(self.num_pages-self.per_pager_num+1,self.num_pages)
        return range(self.current_page-half_part,self.current_page+half_part+1)


def listing(request):
    current_page = request.GET.get('p')
    paginator = CustomPaginator(current_page,11,USER_LIST,10)
    try:
        paginator = paginator.page(current_page)  #獲取前端傳過來顯示當前頁的數據
    except PageNotAnInteger:
        # 若是有異常則顯示第一頁
        paginator = paginator.page(1)
    except EmptyPage:
        # 若是沒有獲得具體的分頁內容的話,則顯示最後一頁
        paginator = paginator.page(paginator.num_pages)

    return render(request,'index.html',{"users":paginator})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ul>
    {% for user in users.object_list %}
        <li>{{ user.name }}-{{ user.age }}</li>
    {% endfor %}

    {% if users.has_previous %}
        <a href="/index?p={{ users.previous_page_number }}">上一頁</a>
    {% endif %}

    {% for number in users.paginator.pager_num_range %}
        {% if number == users.number %}
            <a href="/index?p={{ number }}" style="font-size: 33px">{{ number }}</a>
        {% else %}
            <a href="/index?p={{ number }}" >{{ number }}</a>
        {% endif %}

    {% endfor %}


    {% if users.has_next %}
        <a href="/index?p={{ users.next_page_number }}">下一頁</a>
    {% endif %}
    <span>{{ users.number }} /{{ users.paginator.num_pages }}</span>
</ul>
</body>
</html>

 

沒加特效:

 

2、自定義分頁器

效果:

分頁功能在每一個網站都是必要的,對於分頁來講,其實就是根據用戶的輸入計算出應該在數據庫表中的起始位置。

一、設定每頁顯示數據條數

二、用戶輸入頁碼(第一頁、第二頁...)

三、根據設定的每頁顯示條數和當前頁碼,計算出須要取數據表的起始位置

四、在數據表中根據起始位置取值,頁面上輸出數據

需求,須要在頁面上顯示分頁的頁面。如:[上一頁][1][2][3][4][5][下一頁]

一、設定每頁顯示數據條數

二、用戶輸入頁碼(第一頁、第二頁...)

三、設定顯示多少頁號

四、獲取當前數據總條數

五、根據設定顯示多少頁號和數據總條數計算出,總頁數

六、根據設定的每頁顯示條數和當前頁碼,計算出須要取數據表的起始位置

七、在數據表中根據起始位置取值,頁面上輸出數據

八、輸出分頁html,如:[上一頁][1][2][3][4][5][下一頁]

代碼示例:

 

代碼:

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index2.html$', views.index2),
]

views.py

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

#這裏用的是手動生成數據,生產環境到數據庫中去取數據就能夠啦
USER_LIST = []
for i in range(1,666):
    temp = {'name':'root'+str(i), 'age':i}
    USER_LIST.append(temp)

def index2(request):
    from app01.pager import Pagination
    current_page = request.GET.get('p')
    page_obj = Pagination(666,current_page)

    data_list = USER_LIST[page_obj.start():page_obj.end()]
    return render(request,'index2.html',{'data':data_list,'page_obj':page_obj})

pager.py

class Pagination(object):
    def __init__(self,totalCount,currentPage,perPageItemNum=10,maxPageNum=7):
        # 數據總個數
        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

    def start(self):
        return (self.current_page-1) * self.per_page_item_num

    def end(self):
        return self.current_page * self.per_page_item_num

    @property
    def num_pages(self):
        """
        總頁數
        :return:
        """
        # 666
        # 10
        a,b = divmod(self.total_count,self.per_page_item_num)
        if b == 0:
            return a
        return a+1

    def pager_num_range(self):
        # self.num_pages()
        # self.num_pages
        # 當前頁
        #self.current_page
        # 最多顯示的頁碼數量 11
        #self.per_pager_num
        # 總頁數
        # self.num_pages
        if self.num_pages < self.max_page_num:
            return range(1,self.num_pages+1)
        # 總頁數特別多 5
        part = int(self.max_page_num/2)
        if self.current_page <= part:
            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='/index2.html?p=1'>首頁</a></li>"
        page_list.append(first)

        if self.current_page == 1:
            prev = "<li><a href='#'>上一頁</a></li>"
        else:
            prev = "<li><a href='/index2.html?p=%s'>上一頁</a></li>" %(self.current_page-1,)
        page_list.append(prev)
        for i in self.pager_num_range():
            if i == self.current_page:
                temp = "<li class='active'><a href='/index2.html?p=%s'>%s</a></li>" %(i,i)
            else:
                temp = "<li><a href='/index2.html?p=%s'>%s</a></li>" % (i, i)
            page_list.append(temp)

        if self.current_page == self.num_pages:
            nex = "<li><a href='#'>下一頁</a></li>"
        else:
            nex = "<li><a href='/index2.html?p=%s'>下一頁</a></li>" % (self.current_page + 1,)
        page_list.append(nex)

        last = "<li><a href='/index2.html?p=%s'>尾頁</a></li>" %(self.num_pages,)
        page_list.append(last)

        return ''.join(page_list)

index2.html

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

    <ul class="pagination pagination-sm">
        {{ page_obj.page_str|safe }}
      </ul>
    <div style="height: 300px;"></div>
</body>
</html>

總結:分頁時須要作三件事:

  • 建立處理分頁數據的類
  • 根據分頁數據獲取數據
  • 輸出分頁HTML,即:[上一頁][1][2][3][4][5][下一頁]
相關文章
相關標籤/搜索