# 看下面代碼,我們聲明了我們所需的系統組的常量,聲明為常量是便於代碼的調用
SYSTEM_GROUP_EVERYONE = "Everyone" # 所有人
SYSTEM_GROUP_ANONYMOUS = "Anonymous" # 匿名用戶
SYSTEM_GROUP_USERS = "Users" # 用戶
SYSTEM_GROUP_STAFFS = "Staffs" # 職員
SYSTEM_GROUP_CREATOR = "Creator" # 創建者
SYSTEM_GROUP_OWNER = "Owner" # 所有者
from django.contrib.auth.models import Group """
初始化系統組。
:return:
"""
Group.objects.get_or_create(name=SYSTEM_GROUP_EVERYONE)
Group.objects.get_or_create(name=SYSTEM_GROUP_ANONYMOUS)
Group.objects.get_or_create(name=SYSTEM_GROUP_USERS)
Group.objects.get_or_create(name=SYSTEM_GROUP_STAFFS)
Group.objects.get_or_create(name=SYSTEM_GROUP_CREATOR)
Group.objects.get_or_create(name=SYSTEM_GROUP_OWNER)
def get_user_systemgroups(user):
"""
獲取指定用戶所屬的系統組集合。
:param user: 指定的用戶。
:return: set 表示的用戶所屬的系統組名稱集合。
"""
groups = set()
groups.add(SYSTEM_GROUP_EVERYONE)
if user.is_anonymous():
groups.add(SYSTEM_GROUP_ANONYMOUS)
else:
groups.add(SYSTEM_GROUP_USERS)
if user.is_staff:
groups.add(SYSTEM_GROUP_STAFFS)
return groups
class CreatorMixin(object):
"""
實現創建者的 Model 基類。
"""
def get_creator(self):
"""
獲取對象的創建者,子類重寫該方法實現創建者對象的獲取。
:return: 當前對象的創建者。
"""
return None
def set_creator(self, user):
"""
設置對象的創建者,子類重寫該方法實現創建者對象的設置。
:param creator: 要設置為創建者的User對象。
:return:
"""
pass
class OwnerMixin(object):
"""
實現所有者的 Model 基類。
"""
def get_owner(self):
"""
獲取對象的所有者,子類重寫該方法實現所有者對象的獲取。
:return: 當前對象的所有者。
"""
return None
def set_owner(self, user):
"""
設置對象的所有者,子類重寫該方法實現所有者對象的設置。
:param owner: 要設置為所有者的User對象。
:return:
"""
pass
def get_user_systemgroups_for_obj(user, obj):
"""
獲取指定用戶相對於指定的對象所屬的系統組集合。
:param user: 指定的用戶。
:param obj: 相對於指定的對象。
:return: set 表示的用戶所屬的系統組名稱集合。
"""
groups = set()
if isinstance(obj, CreatorMixin) and obj.get_creator() == user:
groups.add(SYSTEM_GROUP_CREATOR)
if isinstance(obj, OwnerMixin) and obj.get_owner() == user:
groups.add(SYSTEM_GROUP_OWNER)
return groups
# 自定義系統組實現
SYSTEM_GROUP_IMPLEMENTERS = ['systemgroups.systemgroups', '你自己實現的系統組的路徑'…]
def get_user_systemgroups(user):
"""
從所有應用中獲取指定用戶所屬的系統組集合。
:param user: 指定的用戶。
:return: set 表示的用戶所屬的系統組名稱集合。
"""
imps = SYSTEM_GROUP_IMPLEMENTERS
groups = set()
if not imps:
return groups for imp in imps:
imp = importlib.import_module(imp)
if hasattr(imp, "get_user_systemgroups"):
groups.update(imp.get_user_systemgroups(user))
return groups
def get_user_systemgroups_for_obj(user, obj):
"""
從所有應用中獲取指定用戶相對於指定的對象所屬的系統組集合。
:param user: 指定的用戶。
:param obj: 相對於指定的對象。
:return: set 表示的用戶所屬的系統組名稱集合。
"""
imps = SYSTEM_GROUP_IMPLEMENTERS
groups = set()
if not imps:
return groups for imp in imps:
imp = importlib.import_module(imp)
if hasattr(imp, "get_user_systemgroups_for_obj"):
groups.update(imp.get_user_systemgroups_for_obj(user, obj))
return groups
def get_group_permissions(name):
"""
獲取指定名稱的組所擁有的權限集合。
:param name: 組的名稱。
:return: 權限集合。
"""
perms = Permission.objects.filter(group__name = name)
perms = perms.values_list('content_type__app_label', 'codename').order_by()
return set(["%s.%s" % (ct, name) for ct, name in perms])def get_groups_permissions(names):
"""
獲取指定名稱的組所擁有的權限集合。
:param names: 組的名稱集合。
:return: 權限集合。
"""
perms = set()
for name in names:
perms.update(get_group_permissions(name))
return permsclass SystemGroupBackend(object):
def authenticate(self, username=None, password=None, **kwargs):
return None
def has_perm(self, user_obj, perm, obj=None):
return perm in self.get_all_permissions(user_obj, obj)
def get_all_permissions(self, user_obj, obj=None):
perms = self.get_group_permissions(user_obj, obj)
return perms def get_group_permissions(self, user_obj, obj=None):
result_perms = set()
groups = get_user_systemgroups(user_obj)
perms = get_groups_permissions(groups)
result_perms.update(perms)
if obj is None:
return result_perms
groups = get_user_systemgroups_for_obj(user_obj, obj)
perms = get_groups_permissions(groups)
result_perms.update(perms)
return result_perms
class PermMappableMixin(object):
"""
實現權限映射的 Model 基類。
"""
@classmethod
def mapping_permission(cls, perm, obj=None):
"""
根據當前的權限驗證參數,獲取映射後的權限驗證參數。(此類方法僅為標記方法,子類應實現相應的方法)
:param perm: 當前檢測的權限。
:param obj: 當前進行檢測權限的對象。
:return: 返回值包含兩個參數:第一個參數為映射後的權限;第二個參數為對應映射後的對象,其應為映射後權限所對應的 Model 的實例。
"""
return None, None
from django.contrib.contenttypes.models import ContentTypeclass PermMappingBackend(object):
def authenticate(self, username=None, password=None, **kwargs):
return None
def has_perm(self, user_obj, perm, obj=None):
app_label, codename = perm.split('.')
content_types = ContentType.objects.filter(
app_label = app_label,
permission__codename = codename) # 根據權限獲取其對應的ContentType實例。
for content_type in content_types:
model_class = content_type.model_class() # 根據 ContentType 實例獲取對應的 Model 類
if issubclass(model_class, PermMappableMixin):
mapped_perm, mapped_obj = model_class.mapping_permission(perm, obj = obj)
if mapped_perm and user_obj.has_perm(mapped_perm, obj=mapped_obj):
return True
return False
from django.utils.translation import ugettext as _from django.db import modelsclass InfoCategory(models.Model):
name = models.CharField(max_length=128, verbose_name=_('分類名稱'))
class Meta:
permissions = (
("add_info_by_category", _("允許添加分類信息")),
("change_info_by_category", _("允許修改分類信息")),
("delete_info_by_category", _("允許刪除分類信息")),
)class Info(PermMappableMixin, models.Model):
category = models.ForeignKey(InfoCategory, verbose_name=_("所屬分類"))
title = models.CharField(max_length=256, verbose_name=_('標題'))
@classmethod
def mapping_permission(cls, perm, obj=None):
mapped_perm = None
mapped_obj = None
if perm == "permmapping.add_info":
mapped_perm = "permmapping.add_info_by_category"
elif perm == "permmapping.change_info":
mapped_perm = "permmapping.change_info_by_category"
elif perm == "permmapping.delete_info":
mapped_perm = "permmapping.delete_info_by_category"
if isinstance(obj, cls):
mapped_obj = obj.category return mapped_perm, mapped_obj