天天看點

Django學習筆記2023-6-25權限管理

作者:不易9093

假如我有普通工作員、公司上司、員工管理者、通訊錄管理者、文章釋出員、文章審計員、文章管理者等員工身份。文章分為普通文章和進階文章,普通文章所有人可以見,進階文章隻能公司上司可以看見;文章釋出員既可以是普通員工也是可以是公司上司;文章審計員為特定人員,文章發表必須由普通員工或者公司上司釋出後,文章審計員統一後,文章才可以正式釋出。

在應用中models.py的檔案,用于定義文章、使用者權限:

from django.contrib.auth.models import Group, Permission
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.contrib import messages
from .models import UserGroup, UserPermission
from django.contrib.auth.models import Group, Permission
from django.http import HttpResponseForbidden, JsonResponse
from django.urls import reverse_lazy
import json


class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    is_published = models.BooleanField(default=False)
    author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    avatar = models.ImageField(upload_to='avatars/')
    phone = models.CharField(max_length=20)
    email = models.EmailField()
    article_type = models.IntegerField() #普通文章或進階文章
    can_see_all = models.BooleanField(default=True) #所有人可見或隻有公司上司可見
    ctype = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField() #普通文章或進階文章的id字段
    content_object = GenericForeignKey('ctype', 'object_id') #通用外鍵關聯普通文章表或進階文章表中的id字段

class UserGroup(models.Model):
    name = models.CharField(max_length=50)
    description = models.TextField()

class UserPermission(models.Model):
    user_group = models.ForeignKey(UserGroup, on_delete=models.CASCADE)
    permission = models.ForeignKey(Permission, on_delete=models.CASCADE)
    can_add = models.BooleanField(default=False) #是否可以添加聯系人資訊到通訊錄中
    can_change = models.BooleanField(default=False) #是否可以修改通訊錄中的聯系人資訊
# 在Django自帶權限表結構中添加新的權限字段,
# 例如:can_see_article、can_edit_article等。具體操作可參考Django官方文檔。           

上面是個開胃菜~。~

Django學習筆記2023-6-25權限管理
from django.contrib.auth.models import AbstractUser, Group, Permission
from django.db import models
# 定義使用者模型
class User(AbstractUser):
# 添加使用者角色字段
roles = models.ManyToManyField(Group, related_name='users')
def __str__(self):
return self.username
# 定義角色模型
class Role(models.Model):
name = models.CharField(max_length=50, unique=True)
permissions = models.ManyToManyField(Permission, related_name='roles')
def __str__(self):
return self.name
# 定義文章模型
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
# 定義通訊錄模型
class Contact(models.Model):
name = models.CharField(max_length=50)
phone_number = models.CharField(max_length=20)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.name
# 建立權限組
def create_permission_groups():
# 建立普通員工組
ordinary_employee_group, _ = Group.objects.get_or_create(name='Ordinary Employee')
# 建立公司上司組
company_leader_group, _ = Group.objects.get_or_create(name='Company Leader')
# 建立員工管理者組
employee_admin_group, _ = Group.objects.get_or_create(name='Employee Admin')
# 建立通訊錄管理者組
contact_admin_group, _ = Group.objects.get_or_create(name='Contact Admin')
# 建立文章釋出員組
article_publisher_group, _ = Group.objects.get_or_create(name='Article Publisher')
# 建立文章審計員組
article_auditor_group, _ = Group.objects.get_or_create(name='Article Auditor')
# 建立文章管理者組
article_admin_group, _ = Group.objects.get_or_create(name='Article Admin')
# 給各個組配置設定相應的權限
ordinary_employee_group.permissions.add(
# 檢視通訊錄
Permission.objects.get(codename='view_contact'),
# 檢視普通文章
Permission.objects.get(codename='view_article'),
)
company_leader_group.permissions.add(
# 檢視通訊錄
Permission.objects.get(codename='view_contact'),
# 檢視普通文章
Permission.objects.get(codename='view_article'),
# 檢視進階文章
Permission.objects.get(codename='view_advanced_article'),
)
employee_admin_group.permissions.add(
# 檢視通訊錄
Permission.objects.get(codename='view_contact'),
# 添加、修改通訊錄
Permission.objects.get(codename='add_contact'),
Permission.objects.get(codename='change_contact'),
)
contact_admin_group.permissions.add(
# 添加、修改通訊錄
Permission.objects.get(codename='add_contact'),
Permission.objects.get(codename='change_contact'),
)
article_publisher_group.permissions.add(
# 釋出文章
Permission.objects.get(codename='add_article'),
)
article_auditor_group.permissions.add(
# 稽核文章
Permission.objects.get(codename='audit_article'),
)
article_admin_group.permissions.add(
# 添加、修改文章
Permission.objects.get(codename='add_article'),
Permission.objects.get(codename='change_article'),
# 稽核文章
Permission.objects.get(codename='audit_article'),
)
# 建立權限組及權限
create_permission_groups()           

上面的代碼定義了使用者模型User,角色模型Role,文章模型Article以及通訊錄模型Contact。其中,使用者模型繼承了Django自帶的AbstractUser,并添加了一個roles字段用于存儲使用者角色。角色模型包含角色名稱和關聯的權限集合,文章和通訊錄模型分别關聯了建立者(使用者模型)。

在create_permission_groups函數中,我們建立了各個角色組,并為不同角色組配置設定了相應的權限。例如,普通員工組和公司上司組都被授予了檢視通訊錄和檢視普通文章的權限,而公司上司組另外還被授予了檢視進階文章的權限。其他角色組的權限也根據需求進行了配置設定。

需要注意的是,上述代碼僅僅是為了示範如何使用Django自帶的權限系統來實作角色與權限的管理,并未涉及到具體的視圖和路由。在實際項目中,你需要根據具體需求在視圖和路由中使用相應的權限來限制使用者的通路和操作。

真正的結合Django自帶架構的權限管理,參考代碼如下:

from django.contrib.auth.models import User, Group, Permission
from django.contrib.contenttypes.models import ContentType

# 建立組
group_employee = Group.objects.create(name='Employee')
group_manager = Group.objects.create(name='Manager')
group_admin = Group.objects.create(name='Admin')

# 建立使用者
user_employee = User.objects.create_user(username='employee', password='password')
user_manager = User.objects.create_user(username='manager', password='password')
user_admin = User.objects.create_user(username='admin', password='password')

# 将使用者添加到組
user_employee.groups.add(group_employee)
user_manager.groups.add(group_manager)
user_admin.groups.add(group_admin)

# 建立權限
content_type = ContentType.objects.get_for_model(User)

# 普通文章權限
perm_view_article = Permission.objects.create(
    codename='view_article',
    name='Can view article',
    content_type=content_type,
)
group_employee.permissions.add(perm_view_article)

# 進階文章權限
perm_view_advanced_article = Permission.objects.create(
    codename='view_advanced_article',
    name='Can view advanced article',
    content_type=content_type,
)
group_manager.permissions.add(perm_view_advanced_article)

# 公司通訊錄權限
perm_view_contact = Permission.objects.create(
    codename='view_contact',
    name='Can view contact',
    content_type=content_type,
)
group_employee.permissions.add(perm_view_contact)
group_manager.permissions.add(perm_view_contact)

perm_edit_contact = Permission.objects.create(
    codename='edit_contact',
    name='Can edit contact',
    content_type=content_type,
)
group_admin.permissions.add(perm_edit_contact)

# 文章釋出權限
perm_publish_article = Permission.objects.create(
    codename='publish_article',
    name='Can publish article',
    content_type=content_type,
)
group_employee.permissions.add(perm_publish_article)
group_manager.permissions.add(perm_publish_article)

# 文章審計權限
perm_audit_article = Permission.objects.create(
    codename='audit_article',
    name='Can audit article',
    content_type=content_type,
)
group_admin.permissions.add(perm_audit_article)

# 示例用法
if user_employee.has_perm('view_article'):
    print('Employee can view article')

if user_manager.has_perm('view_advanced_article'):
    print('Manager can view advanced article')

if user_employee.has_perm('view_contact'):
    print('Employee can view contact')

if user_admin.has_perm('edit_contact'):
    print('Admin can edit contact')

if user_employee.has_perm('publish_article'):
    print('Employee can publish article')

if user_manager.has_perm('publish_article'):
    print('Manager can publish article')

if user_admin.has_perm('audit_article'):
    print('Admin can audit article')           

以上示例代碼中,我們使用Group模型來建立不同角色的組,并使用User模型建立相應的使用者。然後,我們使用Permission模型來建立不同的權限,并将權限配置設定給相應的組。最後,我們通過has_perm方法來檢查使用者是否擁有某個權限。

方法二:

# models.py

from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    is_employee = models.BooleanField(default=False)  # 是否為普通員工
    is_leader = models.BooleanField(default=False)  # 是否為公司上司
    is_contact_admin = models.BooleanField(default=False)  # 是否為通訊錄管理者
    is_article_publisher = models.BooleanField(default=False)  # 是否為文章釋出員
    is_article_auditor = models.BooleanField(default=False)  # 是否為文章審計員

class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    is_advanced = models.BooleanField(default=False)  # 是否為進階文章

# views.py

from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from django.shortcuts import render

@login_required
def view_contact(request):
    if request.user.is_employee:
        # 普通員工可以檢視公司通訊錄
        # TODO: 傳回通訊錄頁面
        pass

@login_required
@user_passes_test(lambda u: u.is_employee or u.is_leader)
def view_article(request, article_id):
    article = Article.objects.get(id=article_id)
    if article.is_advanced and not request.user.is_leader:
        # 進階文章隻能公司上司可以檢視
        # TODO: 傳回沒有權限檢視進階文章的提示頁面
        pass
    else:
        # TODO: 傳回文章内容頁面
        pass

@login_required
@user_passes_test(lambda u: u.is_contact_admin)
def edit_contact(request):
    # 通訊錄管理者可以釋出、修改通訊錄的姓名、電話号碼等内容
    # TODO: 傳回通訊錄編輯頁面
    pass

@login_required
@user_passes_test(lambda u: u.is_employee or u.is_leader)
def publish_article(request):
    if request.method == 'POST':
        title = request.POST['title']
        content = request.POST['content']
        is_advanced = request.POST.get('is_advanced', False)
        article = Article.objects.create(title=title, content=content, is_advanced=is_advanced)
        if not request.user.is_employee:
            # 文章釋出員是公司上司,直接釋出文章
            # TODO: 傳回文章釋出成功頁面
            pass
        else:
            # 普通員工釋出文章後需要等待審計員稽核
            # TODO: 傳回文章等待稽核頁面
            pass

@login_required
@user_passes_test(lambda u: u.is_article_auditor)
def audit_article(request, article_id):
    article = Article.objects.get(id=article_id)
    # TODO: 稽核文章邏輯
    pass           

以上代碼示範了如何在Django中使用自帶的權限表結構來實作上述員工身份權限控制的功能。通過修改使用者模型,并結合user_passes_test裝飾器,可以實作不同身份的使用者通路不同的視圖函數。在視圖函數中根據使用者的身份和權限進行相應的邏輯處理。

繼續閱讀