FBV
要顯示部落格文章列表,使用 FBV 可以這樣寫:
1 2 3 4 5 6 7 8
| def post_list(request): posts = Post.objects.all() paginator = Paginator(posts, 10) page_number = request.GET.get('page') page_obj = paginator.get_page(page_number) return TemplateResponse(request, 'blog/post_list.html', { 'page_obj': page_obj, })
|
Paginator 類別提供分頁功能,get_page() 回傳一個 Page 物件,包含以下分頁資訊:
page_obj.has_previous:是否有上一頁
page_obj.has_next:是否有下一頁
page_obj.paginator.num_pages:總頁數
page_obj.number:目前頁碼
為了減少重複,可以將分頁邏輯抽出成可重用的輔助函數:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| def post_list(request): posts = Post.objects.all() context = { 'posts':posts } | paged_object_list_context(request, posts, paginate_by=10) return TemplateResponse(request, 'blog/post_list.html', context)
def paged_object_list_context(request, object_list, paginate_by): paginator = Paginator(object_list, paginate_by) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) return { 'page_obj': page_obj, }
|
CBV
使用 class-based ListView 可以大幅簡化:
1 2 3
| class PostListView(ListView): model = Post paginate_by = 10
|
這取代了大量 FBV 程式碼,展現了「convention over configuration」的原則。
簡短一定更好嗎?
CBV 與 FBV 的取捨:
簡潔 vs. 擴展性 — CBV 在處理像分頁這種直觀的 view 時表現出色,但當需要加入自定義邏輯(權限過濾、統計計算、複雜表單處理)時,就需要深入了解內部機制,大量使用 Mixin 或覆寫方法。
CBV 的隱藏複雜性 — 看似乾淨的程式碼背後,隱藏著難以追蹤的邏輯。修改預設行為往往需要覆寫多個內部方法或組合 Mixin,增加學習成本與程式碼複雜度。
如何選擇 FBV 和 CBV — 當 view 邏輯簡單且固定時,CBV 確實提供了便利。但隨著業務邏輯複雜度增加,FBV 的靈活性和控制力更佳。合理的結構和清晰的邏輯,才是程式碼真正的價值。
參考資料:
Django Views — The Right Way
Django Docs
評論