1. 程式人生 > >08 用Django分頁器實現文章分頁

08 用Django分頁器實現文章分頁

1、概述

Django有自帶的分頁器,可以將資料分在不同的頁面中,並提供一些屬性和方法實現對分頁資料的操作。分頁功能的類位於django/core/paginator.py中。

2、資料準備

在具體實現分類器功能前,首先準備一頁網頁類似與豆瓣電影展示。網頁中的主要資料是圖片,主題,內容等。其資料表格式型別如下:

class Video(models.Model):
    title = models.CharField(null=True, blank=True, max_length=300)
    content = models.TextField(null=True, blank=True)
    url_image = models.URLField(null=True, blank=True)
    editors_choice = models.BooleanField(default=False)
    def __str__(self):
        return self.title
對應部分網頁顯示如下,其中網頁中帶有分頁按鈕:

django後臺資料結構如下:


3、使用Django分頁器

1)在views.py層引入django的分頁器,並通過(資料,頁面資料個數)格式進行分頁

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

def listing(request):
    context = {}
    vids_list = Video.objects.all()
    page_robot = Paginator(vids_list, 9) #每頁顯示9個數據
    try:
        vids_list = page_robot.page(request.GET.get('page'))
    except PageNotAnInteger: #判斷頁碼是否為數值,如果不是,則返回第一頁
        vids_list = page_robot.page(1)
    except EmptyPage: #判斷是否為空頁面,如果是,則返回最後一頁
        vids_list =  page_robot.page(page_robot.num_pages)
    context['vids_list'] = vids_list
    return render(request, 'listing.html', context)

解析:

a、首先要引用django的分頁器Paginator;

b、分頁器使用的格式是有兩個引數,第一個是進行分頁的資料,第二個是顯示每頁的資料數量;

c、對網頁的資料進行分頁後,資料量都是有限的。因此在使用過程中可能會出現在網址中的資料頁數大於分頁數,則通過EmptyPage的異常來返回最後一頁資料,

其中num_pages是分頁器的屬性,剛好返回最後一頁的頁碼。

d、有可能你會在網址中輸入非數值型別的頁碼,這樣就不符合django分頁器的設定。此時通過PageNotAnInteger異常捕獲來返回第一頁的資料。

2)同時在template模板層實現分頁按鈕的操作

<div class="ui pagination menu">
  {% if vids_list.has_previous %}
    <a href="?page={{ vids_list.previous_page_number }}" class="item">
        <i class="icon red left arrow"></i>
    </a>
  {% else %}
    <a href="?page={{ vids_list.start_index }}" class="item">
        <i class="icon left arrow"></i>
    </a>
  {% endif %}

  {% if vids_list.has_next %}
    <a href="?page={{ vids_list.next_page_number }}" class="item">
        <i class="icon red right arrow"></i>
    </a>
  {% else %}
    <a href="?page={{ vids_list.end_index }}" class="item">
        <i class="icon right arrow"></i>
    </a>
  {% endif %}
</div>
解析:

a、通過分頁器操作的資料vids_list具有一些屬性和方法,其中這邊用到了has_previous/has_next來判斷當前頁是否有前一頁/後一頁;

b、如果當前頁有has_previous,則通過previous_page_number屬性來得到前一頁的具體頁碼,可將連結返回到網址中;

c、如果當前頁已經是首頁(即has_previous返回為False),則通過start_index屬性來得到第一條資料的索引即為1;

d、使用has_next的方法與has_previous操作類似。

4、實現後臺圖片的上傳

1)在上述的例子中,網頁的圖片都是url格式存在url_image中的。要想實現在本地後臺上傳圖片,首先需要在models.py層增加FileField欄位

如下cover

class Video(models.Model):
    title = models.CharField(null=True, blank=True, max_length=300)
    content = models.TextField(null=True, blank=True)
    url_image = models.URLField(null=True, blank=True)
    editors_choice = models.BooleanField(default=False)
    cover = models.FileField(upload_to='cover_image', null=True) #該欄位為增加的欄位,型別為FileField,且上傳的圖片會儲存到cover_image資料夾中
    def __str__(self):
        return self.title
2)在settings.py中設定upload檔案路徑


解析:

a、通過在settings.py中設定MEDIA_URL檔案為箭頭指向的upload,然後在MEDIA_ROOT中進行預設檔案位置替換;

b、這樣做的目的是將上傳的圖片等儲存在本地資料夾中。

3)在urls.py中設定開發者使用模式

    from django.conf.urls.static import static

    if settings.DEBUG:
        urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
        urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
解析:在urls.py層增加如上程式碼,表明在本地開發時會引用本地的靜態檔案和MEDIA儲存的檔案,而在伺服器上部署時會忽略。

4)修改模板層圖片的顯示

<div class="image">
  {% if vid.cover %}
    <img src="/upload/{{ vid.cover }}" alt="" style="height:200px;object-fit: cover;">
  {% else %}
    <img src="{{ vid.url_image }}" alt="" style="height:200px;object-fit: cover;">
  {% endif %}
</div>
解析:通過vid.cover判斷,來實現不同圖片的網頁載入。如果cover欄位存在,則引用upload/cover_image資料夾中的圖片;如果不存在,則引用url_image欄位圖片。

5)在django後臺進行操作

解析:在django後臺中的cover欄位處,會出現“選擇檔案”按鈕,通過點選按鈕選擇相關圖片,即可上傳本地圖片。