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

如何通过装饰器为DRF的ModelViewSet各方法配置不同权限

给Django REST Framework ModelViewSet方法用装饰器设置权限的正确方式

嘿,我懂你想通过装饰器给ModelViewSet的不同方法单独配置权限的需求,咱们来拆解这个问题:

首先得说清楚:你之前直接用@permission_classes()装饰ViewSet方法的写法为什么没用——DRF的@permission_classes装饰器是为视图类设计的,不是为单个方法准备的。ViewSet的方法最终会被映射成「动作(action)」,DRF的权限检查流程默认只会读取类级别的permission_classes属性,不会去识别方法上的装饰器配置。哪怕你用了@method_decorator,也没法让DRF的权限系统正确读取到方法上的权限设置。

那如果一定要用装饰器实现这个需求,我们可以自己写一个自定义装饰器,临时替换当前方法执行时的权限配置,执行完再恢复。具体代码如下:

步骤1:自定义方法级权限装饰器

def method_permission_classes(permission_classes):
    def decorator(func):
        def wrapped_func(self, *args, **kwargs):
            # 保存原有的权限类配置
            original_perms = self.permission_classes
            # 临时替换为当前方法需要的权限类
            self.permission_classes = permission_classes
            # 重新生成权限实例(因为get_permissions会缓存实例)
            self.permissions = self.get_permissions()
            
            try:
                # 执行原方法逻辑
                return func(self, *args, **kwargs)
            finally:
                # 执行完毕后恢复原来的权限配置
                self.permission_classes = original_perms
                self.permissions = self.get_permissions()
        return wrapped_func
    return decorator

步骤2:在ViewSet方法上使用装饰器

from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
from your_app.permissions import CustomPermission

class abcd(viewsets.ModelViewSet):
    @method_permission_classes([IsAuthenticated])
    def list(self, request, format=None):
        try:
            # 你的list方法逻辑
            pass
        except Exception as e:
            # 异常处理
            pass

    @method_permission_classes([CustomPermission])
    def create(self, request, format=None):
        try:
            # 你的create方法逻辑
            pass
        except Exception as e:
            # 异常处理
            pass

补充说明

这个自定义装饰器的原理是:在方法执行前临时修改当前视图实例的permission_classes属性,重新生成权限实例;方法执行完成后再恢复原配置,避免影响其他方法的权限检查。

不过要提一句:DRF官方更推荐的还是你已经知道的get_permissions()重写方式,因为这种写法更符合DRF的设计逻辑,代码可读性也更高,不需要额外维护自定义装饰器。比如:

def get_permissions(self):
    if self.action == 'create':
        return [CustomPermission()]
    elif self.action == 'list':
        return [IsAuthenticated()]
    return super().get_permissions()

内容的提问来源于stack exchange,提问作者Ab1gor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:48:37