文章

Django - 許可權系統

今天我們將探討 Django 的許可權系統,它提供了強大的功能來管理使用者的操作權限。我們將學習如何設定模型的許可權、自訂許可權,以及如何使用群組來簡化權限管理。


課程目標

  • 瞭解 Django 許可權系統的基本概念。
  • 設定內建與自訂許可權。
  • 使用群組進行權限管理。
  • 在視圖中進行權限檢查。

課程內容

1. Django 許可權系統概述

Django 的許可權系統基於以下三個核心概念:

  1. 用戶(User):可以被分配特定的許可權。
  2. 群組(Group):用於集合一組用戶並分配相同的許可權。
  3. 許可權(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 許可權系統的核心概念。
  • 瞭解如何設置內建與自訂許可權。
  • 使用群組來簡化用戶權限管理。
  • 實作視圖與模板中的許可權檢查。

作業

  1. 在 Blog 系統中,為群組「編輯者」設置僅能修改與刪除文章的許可權。
  2. 為用戶新增「重置密碼」功能,限制只有特定用戶能執行該操作。
  3. 編寫單元測試驗證用戶的群組與許可權配置是否正確。

本文章以 CC BY 4.0 授權