以下文章是 Django 類別基於視圖(CBV)探索系列的 第七篇,主要探討如何利用 Mixin 來 重複使用共通功能,並有效地實現 權限管理 及 登入檢查。在上一篇文章(第六篇)中,我們使用 TemplateView
和 RedirectView
自動化了簡單的頁面渲染和重定向,現在讓我們來了解如何最大化 CBV 的 重用性 和 擴展性。
前篇直接連結,請點擊以下鏈接!
TemplateView & RedirectView 使用方法
“提高 Django Mixin 的代碼重用性,
輕鬆實現權限及登入檢查!”
1. Mixin,為何需要?
Django CBV 本身提供了強大的重用性,但如果在多個視圖中有 共通需要的功能,該如何處理呢?例如,進入特定頁面時,通常需要 登入,或僅允許具備 特定權限 的用戶進入。這時出現的概念就是 Mixin。
Mixin 是利用 多重繼承 的概念,將 相同的方法或屬性注入 多個類別。透過在視圖類中繼承特定功能的 Mixin 類別,我們可以減少 重複代碼,提高 維護性。
主要 Mixin 使用範例:
- 權限管理: 驗證訪問特定視圖的用戶是否已登入,或其是否擁有特定權限。
- 表單處理邏輯: 處理多個表單所需的共通數據預處理或後處理邏輯。
- 模板上下文: 添加必須傳遞到所有視圖的上下文數據。
- 日誌記錄: 為特定視圖的執行前後添加日誌功能。
2. Django 的代表性 Mixin 使用法: LoginRequiredMixin
最常使用的 Mixin 之一就是 LoginRequiredMixin
。顧名思義,該視圖必須強制要求用戶 登入 才可進入。
2.1 LoginRequiredMixin 使用法
LoginRequiredMixin
包含在 django.contrib.auth.mixins
模組中。
# views.py
from django.views.generic import ListView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Post # 示例模型
class MyPostListView(LoginRequiredMixin, ListView):
model = Post
template_name = 'posts/my_posts.html'
context_object_name = 'posts'
# 登入狀態下的用戶進入時的重定向 URL 設定 (選擇性)
# login_url = '/accounts/login/' # settings.LOGIN_URL 為預設值
# redirect_field_name = 'next' # 登入後返回原頁面的查詢參數名稱 (預設值)
- 繼承順序: 首先繼承
LoginRequiredMixin
,再繼承 Django 的 Generic View (此處為ListView
)。通常因為 Mixin 是為了添加功能,所以把它放在核心視圖類之前是慣例。 LoginRequiredMixin
如果用戶未登入,將自動重定向到settings.LOGIN_URL
指定的登入頁面。成功登入時亦可透過next
查詢參數返回到原請求的頁面。
2.2 urls.py 連結
應用 LoginRequiredMixin
的視圖與一般 CBV 相同,連結到 urls.py
。
# urls.py
from django.urls import path
from .views import MyPostListView
urlpatterns = [
path('my-posts/', MyPostListView.as_view(), name='my_posts'),
]
現在當訪問 /my-posts/
路徑時,如果未登入,將自動重定向到登入頁面。
3. 權限管理的 Mixin: PermissionRequiredMixin & UserPassesTestMixin
如果 LoginRequiredMixin
強制要求登入,那麼 PermissionRequiredMixin
和 UserPassesTestMixin
則需要 具備特定權限 或滿足 特定條件 才可以訪問。
3.1 PermissionRequiredMixin 使用法
與 Django 的權限系統整合,僅允許擁有特定 permission
的用戶訪問。
# views.py
from django.views.generic import CreateView
from django.contrib.auth.mixins import PermissionRequiredMixin
from .models import Article
from .forms import ArticleForm
class ArticleCreateView(PermissionRequiredMixin, CreateView):
model = Article
form_class = ArticleForm
template_name = 'articles/article_form.html'
success_url = '/articles/'
# 用 'app_label.permission_codename' 格式指定權限
permission_required = 'app_label.add_article'
# 若有多種權限之一也允許的情況下:
# permission_required = ('app_label.add_article', 'app_label.change_article')
# raise_exception = True # 無權限時拋出 403 Forbidden 錯誤 (預設為重定向到登入頁)
permission_required
: 將訪問所需的權限指定為字符串(一個或元組)。主要使用 Django 的auth
應用自動生成的權限 (add_model
,change_model
,delete_model
,view_model
)。
3.2 UserPassesTestMixin 使用法
當想檢查更為 複雜或自定義的條件 時使用。例如,要限制只能修改自己寫的評論,或者只能讓特定組的用戶進入等邏輯上非常有用。
# views.py
from django.views.generic import UpdateView
from django.contrib.auth.mixins import UserPassesTestMixin
from .models import Comment
from .forms import CommentForm
class CommentUpdateView(UserPassesTestMixin, UpdateView):
model = Comment
form_class = CommentForm
template_name = 'comments/comment_form.html'
success_url = '/comments/'
# 覆蓋 test_func 方法來檢查條件
def test_func(self):
comment = self.get_object()
# 確認當前登入用戶是否為評論作者
return self.request.user == comment.author or self.request.user.is_superuser
# raise_exception = True # 測試失敗時拋出 403 Forbidden 錯誤
test_func()
方法返回 True 將允許訪問,返回 False 則拒絕訪問。self.request.user
可以用來存取當前登入的用戶對象。
4. 自定義 Mixin 的製作
除了 Django 提供的 Mixin 外,還可以製作 自己的 Mixin 以便在多個視圖中重複使用。例如,讓我們製作一個添加所有頁面共通的 current_year
上下文的 Mixin。
# common/mixins.py
from datetime import datetime
class CurrentYearMixin:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['current_year'] = datetime.now().year
return context
# views.py (使用範例)
from django.views.generic import TemplateView
from .common.mixins import CurrentYearMixin
class MyCustomPageView(CurrentYearMixin, TemplateView):
template_name = 'my_custom_page.html'
# my_custom_page.html (在模板中使用)
<footer>© {{ current_year }} 我的網站</footer>
CurrentYearMixin
覆蓋get_context_data
方法以添加current_year
到上下文中。呼叫super().get_context_data(**kwargs)
以保持父類(或其他 Mixin)的上下文數據非常重要。
5. 與 FBV 的比較
功能 | FBV (函數基於視圖) | CBV + Mixin |
登入/權限檢查 | @login_required , @permission_required 裝飾器使用。 <br> 自定義條件可以在函數內直接編寫 if not request.user.is_authenticated: return redirect(...) 。 |
LoginRequiredMixin, PermissionRequiredMixin, UserPassesTestMixin 等 Mixin 繼承簡單應用。 <br> 雖然與裝飾器相似,但更符合 CBV 結構。 |
代碼重用性 | 將共通邏輯分離為單獨函數以呼叫,或直接編寫函數裝飾器。 <br> 容易出現重複代碼。 | 通過 Mixin 將所需功能模塊化,通過多重繼承注入。 <br> 結構遠比 FBV 更清晰,重用性高。 |
代碼可讀性 | 每個函數中可能重複條件檢查邏輯。 | 僅查看視圖類的繼承列表即可輕鬆了解已應用的功能(權限、登入等)。 |
維護性 | 添加新功能時,可能需要修改多個函數。 | 僅修改 Mixin 類即可在所有使用該 Mixin 的視圖中生效。 |
開發生產力(關鍵字) | “每個函數單獨處理,重複工作的可能性” | “模組化,易於功能擴展,遵循 DRY(不要重複自己)原則,提高生產力” |
6. 總結及下一篇預告
Mixin 是 Django 類別基於視圖的 真正力量,使我們能夠最大化 代碼重用性,模組化 共通功能,降低視圖類的複雜性,特別是在 身份驗證及權限管理 等網絡應用的必備元素上更加高效實現。
到目前為止,我們已經了解了從 CBV 的基本使用方法到複雜的 CRUD,以及通過 Mixin 擴展功能,幾乎探索了 Django CBV 所有的核心要素。
下一篇(系列第八篇)將會總結如何在實際項目中應用之前所講的 CBV,在 複雜場景 中的組合運用,以及 CBV 的優點與局限。
重新查看舊文
- 類別基於視圖(CBV)探索系列 #1 – 為何從 FBV 轉向 CBV 及開發者心態
- 類別基於視圖(CBV)探索系列 #2 – 理解 Django 的基本 View 類別
- 類別基於視圖(CBV)探索系列 #3 – 通過 FormView 簡化表單處理
- 類別基於視圖(CBV)探索系列 #4 – ListView & DetailView 使用法
- 類別基於視圖(CBV)探索系列 #5 – 使用 CreateView、UpdateView、DeleteView 實現 CRUD
- 類別基於視圖(CBV)探索系列 #6 – TemplateView & RedirectView 使用法
“利用 Mixin 最大化 Django CBV 的潛力,
構建易於維護且可擴展的網絡應用!”
目前沒有評論。