[Django 30Days] Day12 Blog實作範例一頁面分頁器Plus
D12 基礎的分頁結束後,讓我們將分頁功能優化吧!
- 目前是由每五篇做一次分頁,但是當文章越來越多時,頁碼會越來越多可能會影響版面。
- 目前並沒有顯示當前頁面是哪一頁。
myblog/post_list.htmltemplate修改<!--全部頁碼-->
{% for page_num in page_of_posts.paginator.page_range%} <!--if else endif-->
{% if page_num == page_of_posts.number %}
<li class="page-item active"><a class="page-link" href="?page={{ page_num }}">{{ page_num }}</a></li>
{% else %}
<li><a class="page-link" href="?page={{ page_num }}">{{ page_num }}</a></li>
{% endif %}{% endfor %}用 if else endif 判斷如果當前頁面編號是page_of_posts.number則利用class page-item active標示,其他則正常顯示。
接著我們可以從/admin頁面或是用shell指令多新增幾篇文章後再繼續。
而當文章新增後會發現頁碼也會無止境的增加,最後會影響排版,因此需要在views.py稍微設計一下程式,只要顯示當前頁面的前兩頁或後兩頁即可。
myblog/views.py
class PostListView(View):
template_name = 'myblog/post_list.html'
def get(self, request, *args, **kwargs):
post_list = BlogPost.objects.all().order_by("-created_at")
paginator = Paginator(post_list, 5) #每5篇文進行分頁
page_num = request.GET.get('page', 1) #get url 頁面參數
page_of_posts = paginator.get_page(page_num)
curr_page_num = page_of_posts.number #取現在頁碼
page_range_display = [curr_page_num - 2, curr_page_num -1,
curr_page_num, curr_page_num + 1, curr_page_num +2] context = {}
context['posts'] = page_of_posts.object_list
context['page_of_posts'] = page_of_posts
context['page_range_display'] = page_range_display
context['category_list'] = BlogPostCategory.objects.all()
return render(request, self.template_name, context)"""
curr_page_num = page_of_posts.number #取得現在頁面後將頁面 +-2頁存入page_range_display的list裡面,最後存成context['page_range_display']回傳。
"""接著在
post_list.html中修改全部頁碼下面的迭代。
<!--全部頁碼-->
{% for page_num in page_range_display%}
成功實現了顯示現在頁面標示與前後兩頁顯示,但是有個問題,我們頁首並沒有-1頁、0頁,同樣頁尾也沒有多餘的兩頁,因此需要對此做一些處理。
myblog/views.py#PostListView
page_range_display = [curr_page_num - 2, curr_page_num -1,
curr_page_num, curr_page_num + 1, curr_page_num +2]
修改為
page_range_display = \
list(range(max(curr_page_num -2,1), curr_page_num)) +\
list(range(curr_page_num, min(curr_page_num + 2, paginator.num_pages) + 1))利用range()來決定開始與結束頁碼。
頁首部分:配合max(x,y),如果x-2>1的話就會取x-2這個數字當範圍的開始,若沒有的話範圍的開始則為1,而range的結束則為當前頁面。頁尾部分:配合min(x,y), 如果x+2<全部頁碼數的話就取X+2這個數字當範圍的結束,若沒有的話則取全部頁碼數當範圍的結束,結尾記得要+1。
多於頁數的問題解決!但是如果這樣一個一個點也很不方便,因此打算加上第一頁與最後一頁提升使用者體驗。
myblog/views.py
PostListView
新增判斷#前頁碼省略記號與後頁碼省略記號
if page_range_display[0] - 1 >= 2:
page_range_display.insert(0, "...")if paginator.num_pages - page_range_display[-1] >= 2:
page_range_display.append('...')#第一頁與最後一頁
if page_range_display[0] != 1:
page_range_display.insert(0,1)if page_range_display[-1] != paginator.num_pages:
page_range_display.append(paginator.num_pages)<!--post_list.html-->
修改全部頁碼底下的判斷,如果 page_num = ... 沒連結直接顯示省略記號,其他則為其他頁面連結。
<!--全部頁碼-->
{% for page_num in page_range_display%}
{% if page_num == page_of_posts.number %}
<li class="page-item active"><a class="page-link" href="?page={{
page_num }}">{{ page_num }}</a></li>
{% else %}
{% if page_num == "..." %}
<li>{{ page_num }}</li>
{% else %}
<li><a class="page-link" href="?page={{ page_num }}">{{
page_num }}</a></li>
{% endif %}
{% endif %}
{% endfor %}在頁碼實現</ul>標籤結束的地方加入頁面資訊。
<p>
目前正在第 {{ page_of_posts.number }} 頁, 共 {{ page_of_posts.paginator.num_pages }} 頁
</p>
在文章列表post_list.html頁面的分頁器完成了!
但是在分類頁面的分類器尚未實現,因此接下來要去完善它,直接把PostListView的code貼到PostCategoryView進行修改。
myblog/views.py
PostCategoryViewclass PostCategoryView(View):
template_name = 'myblog/post_category.html'
def get(self, request, pk):
category = get_object_or_404(BlogPostCategory, pk=pk) #取類別
post_list = BlogPost.objects.filter(category=category) #通過類別篩選需要的文章
paginator = Paginator(post_list, 5) #每5篇文進行分頁
page_num = request.GET.get('page', 1) #get url 頁面參數
page_of_posts = paginator.get_page(page_num)
curr_page_num = page_of_posts.number #取現在頁碼 #取現在頁碼前後兩頁的範圍
page_range_display = list(range(max(curr_page_num -2,1),
curr_page_num)) + \
list(range(curr_page_num, min(curr_page_num + 2,
paginator.num_pages) + 1)) #前頁碼省略記號與後頁碼省略記號
if page_range_display[0] - 1 >= 2:
page_range_display.insert(0, "...")
if paginator.num_pages - page_range_display[-1] >= 2:
page_range_display.append('...')
#第一頁與最後一頁
if page_range_display[0] != 1:
page_range_display.insert(0,1)
if page_range_display[-1] != paginator.num_pages:
page_range_display.append(paginator.num_pages) context = {}
context['post_by_categories'] = category
context['posts'] = page_of_posts.object_list
context['page_of_posts'] = page_of_posts
context['page_range_display'] = page_range_display
context['category_list'] = BlogPostCategory.objects.all()
return render(request, self.template_name, context)比PostListView多一件事,先取得類別,再通過類別篩選此類別相關的文章。
由於分類頁面的html版面之前沒有修改,因此也要將post_category.html頁面改為與post_list.html一樣的版面。
行14:增加返回文章列表。
分頁器在這告一段落,在使用場景上除了頁面上資料過多要進行分頁外,也有其他範例是在admin後台系統美化時使用,這兩篇,我們嘗試使用了分頁器進行分頁與相關優化提升使用者體驗。
到目前第十二天,在前端的部分雖然框架有很多內建或支援的套件很方便,但在美化、優化還是得進行html、CSS、JS的學習,有些功能只用框架內容是無法滿足的,還是得回歸到前端技能加強。
在頁面上或分頁上設計作法不只一種除了自己使用的舒適以外,也可以訪談使用者或設定意見調查表,提升使用者體驗。
Referece:
楊仕航blog
Django documentation