Django中如何向自定义权限类传递allowed_groups参数?
自定义DRF权限类传递allowed_groups参数的正确实现方式
问题描述
我有一个继承自Django REST Framework BasePermission的自定义权限类,希望传递一个allowed_groups参数,该参数为允许访问特定视图的用户组列表。
当前自定义权限实现:
class CustomUserPermisions(BasePermission): message = "Ooops! You do not have permissions to access this particular site" def has_permission(self, request, view): allowed_groups = [ 'group_hr', 'super_admin', 'employee'] user1 = Employee.objects.filter(user__email=request.user).first() user_groups = user1.user_group.all() for group in user_groups: if group.title in allowed_groups: return True return False
尝试添加参数时错误写法:
class CustomUserPermisions(BasePermission, allowed_groups): message = "Ooops! You do not have permissions to access this particular site" def has_permission(self, request, view): allowed_groups = [ 'group_hr', 'super_admin', 'employee'] user1 = Employee.objects.filter(user__email=request.user).first() user_groups = user1.user_group.all() for group in user_groups: if group.title in allowed_groups: return True return False
触发的错误:
NameError: name 'allowed_groups' is not defined
解决方案
方法一:权限类支持初始化传参
通过给权限类添加__init__方法,接收allowed_groups参数,实现不同视图灵活配置允许的组:
from rest_framework.permissions import BasePermission class CustomUserPermissions(BasePermission): message = "Ooops! You do not have permissions to access this particular site" def __init__(self, allowed_groups=None): # 设置默认允许的组,未传参时使用该值 self.allowed_groups = allowed_groups or ['group_hr', 'super_admin', 'employee'] def has_permission(self, request, view): # 优化:直接使用request.user关联Employee,无需通过邮箱过滤 user_employee = Employee.objects.filter(user=request.user).first() if not user_employee: return False # 用集合优化组判断效率 allowed_groups_set = set(self.allowed_groups) for group in user_employee.user_group.all(): if group.title in allowed_groups_set: return True return False
视图中使用示例:
from rest_framework.views import APIView class HROnlyView(APIView): # 仅允许group_hr组访问 permission_classes = [CustomUserPermissions(allowed_groups=['group_hr'])] def get(self, request): # 视图逻辑 return Response({"message": "HR access only"})
方法二:通过视图类属性传递参数
如果不想修改权限类的初始化逻辑,可以在视图中定义allowed_groups属性,权限类读取该属性:
class CustomUserPermissions(BasePermission): message = "Ooops! You do not have permissions to access this particular site" # 默认允许的组列表 default_allowed_groups = ['group_hr', 'super_admin', 'employee'] def has_permission(self, request, view): # 优先使用视图定义的allowed_groups,无定义则用默认值 allowed_groups = getattr(view, 'allowed_groups', self.default_allowed_groups) user_employee = Employee.objects.filter(user=request.user).first() if not user_employee: return False allowed_groups_set = set(allowed_groups) return any(group.title in allowed_groups_set for group in user_employee.user_group.all())
视图中使用示例:
class EmployeeOnlyView(APIView): permission_classes = [CustomUserPermissions] # 定义允许访问的组 allowed_groups = ['employee'] def get(self, request): return Response({"message": "Employee access only"})
关键优化说明
- 原代码中
request.user是用户对象,直接用user=request.user关联Employee更高效,无需通过邮箱过滤。 - 使用集合(
set)替代列表判断组是否存在,将时间复杂度从O(n)降到O(1),提升性能。
内容的提问来源于stack exchange,提问作者manu langat
相关产品推荐
相关产品推荐

