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欄位處,會出現“選擇檔案”按鈕,通過點選按鈕選擇相關圖片,即可上傳本地圖片。