You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 22:12:24