Django - 許可權系統
今天我們將探討 Django 的許可權系統,它提供了強大的功能來管理使用者的操作權限。我們將學習如何設定模型的許可權、自訂許可權,以及如何使用群組來簡化權限管理。
課程目標
- 瞭解 Django 許可權系統的基本概念。
- 設定內建與自訂許可權。
- 使用群組進行權限管理。
- 在視圖中進行權限檢查。
課程內容
1. Django 許可權系統概述
Django 的許可權系統基於以下三個核心概念:
- 用戶(User):可以被分配特定的許可權。
- 群組(Group):用於集合一組用戶並分配相同的許可權。
- 許可權(Permission):控制用戶可以執行的操作。
2. 模型內建許可權
Django 自動為每個模型生成以下三個許可權:
add_<model_name>
:允許新增記錄。change_<model_name>
:允許修改記錄。delete_<model_name>
:允許刪除記錄。
例如,對於模型 Post
,Django 將自動生成:
add_post
change_post
delete_post
檢查許可權
可以使用 has_perm()
方法檢查用戶是否具備某個許可權:
1
2
if request.user.has_perm('app_name.add_post'):
# 用戶具備新增文章的許可權
3. 自訂許可權
3.1 定義自訂許可權
可以在模型的 Meta
類中定義自訂許可權:
1
2
3
4
5
6
7
8
9
10
11
12
13
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200, verbose_name="標題")
content = models.TextField(verbose_name="內容")
author = models.CharField(max_length=100, verbose_name="作者")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="建立時間")
class Meta:
permissions = [
('publish_post', 'Can Publish Post'),
('archive_post', 'Can Archive Post'),
]
3.2 應用遷移
在添加自訂許可權後,需要執行數據庫遷移:
1
2
python manage.py makemigrations
python manage.py migrate
4. 群組管理
4.1 創建群組
可以通過 Django 的管理後台或程序創建群組。以下是程式化創建群組的示例:
1
2
3
4
5
6
7
8
9
10
11
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from .models import Post
# 創建 "Editors" 群組
editors_group, created = Group.objects.get_or_create(name="Editors")
# 為群組分配許可權
content_type = ContentType.objects.get_for_model(Post)
permissions = Permission.objects.filter(content_type=content_type, codename__in=['add_post', 'change_post'])
editors_group.permissions.set(permissions)
4.2 分配群組
將用戶分配到群組:
1
user.groups.add(editors_group)
4.3 檢查群組權限
檢查用戶是否屬於某群組:
1
2
if request.user.groups.filter(name='Editors').exists():
# 用戶屬於 "Editors" 群組
5. 在視圖中檢查許可權
5.1 使用裝飾器
Django 提供了 @permission_required
裝飾器來檢查許可權:
1
2
3
4
5
from django.contrib.auth.decorators import permission_required
@permission_required('app_name.publish_post')
def publish_post(request, post_id):
# 用戶具備發布文章的許可權
5.2 在 CBV 中檢查許可權
對於基於類別的視圖(CBV),可以使用 PermissionRequiredMixin
:
1
2
3
4
5
6
7
8
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.views.generic import UpdateView
from .models import Post
class PostUpdateView(PermissionRequiredMixin, UpdateView):
model = Post
fields = ['title', 'content']
permission_required = 'app_name.change_post'
6. 示例:限制文章的發布功能
6.1 視圖實作
在 views.py
中新增一個檢查許可權的功能:
1
2
3
4
5
6
7
8
9
10
from django.shortcuts import get_object_or_404, redirect
from django.contrib.auth.decorators import permission_required
from .models import Post
@permission_required('app_name.publish_post')
def publish_post(request, post_id):
post = get_object_or_404(Post, id=post_id)
post.is_published = True
post.save()
return redirect('post_list')
6.2 模板按鈕
根據用戶的許可權,顯示或隱藏操作按鈕:
1
2
3
{% if user.has_perm('app_name.publish_post') %}
<a href="{% url 'publish_post' post.id %}">發布文章</a>
{% endif %}
7. 測試許可權系統
7.1 使用管理後台
- 創建一個新用戶並分配特定許可權。
- 使用該用戶登入,檢查操作權限是否正確。
7.2 單元測試
編寫測試來驗證許可權的工作狀況:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from django.test import TestCase
from django.contrib.auth.models import User, Permission
from .models import Post
class PermissionTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='testuser', password='password')
self.post = Post.objects.create(title="測試文章", content="測試內容", author="作者")
def test_publish_permission(self):
self.user.user_permissions.add(Permission.objects.get(codename='publish_post'))
self.client.login(username='testuser', password='password')
response = self.client.post(f'/publish/{self.post.id}/')
self.assertEqual(response.status_code, 200)
self.post.refresh_from_db()
self.assertTrue(self.post.is_published)
8. 本日總結
- 學習 Django 許可權系統的核心概念。
- 瞭解如何設置內建與自訂許可權。
- 使用群組來簡化用戶權限管理。
- 實作視圖與模板中的許可權檢查。
作業
- 在 Blog 系統中,為群組「編輯者」設置僅能修改與刪除文章的許可權。
- 為用戶新增「重置密碼」功能,限制只有特定用戶能執行該操作。
- 編寫單元測試驗證用戶的群組與許可權配置是否正確。
本文章以 CC BY 4.0 授權