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

Django自定义权限实现方法及permission_classes装饰器原理解析

DRF 自定义权限实现与 @permission_classes 装饰器原理解析

一、自定义权限实现步骤

DRF 所有权限类都继承自 BasePermission 基类,自定义权限只需要继承该类,重写对应校验方法即可:

  • 重写 has_permission(request, view):控制全局视图级别的访问权限,所有请求进入视图前都会先触发该方法校验
  • 重写 has_object_permission(request, view, obj):控制单对象级别的访问权限,只有操作单个具体资源(比如查询、修改单条数据)时才会触发该方法校验

示例1:全局视图级权限(仅邮箱验证用户可访问)

from rest_framework.permissions import BasePermission

class IsEmailVerified(BasePermission):
    message = "请先完成邮箱验证" # 自定义权限不通过时的提示信息

    def has_permission(self, request, view):
        return bool(
            request.user.is_authenticated
            and request.user.email_verified == True
        )

示例2:单对象级权限(仅资源所有者可操作)

class IsResourceOwner(BasePermission):
    message = "你不是该资源的所有者,无权操作"

    def has_object_permission(self, request, view, obj):
        # 此处以资源关联的创建用户字段为例,可根据业务自行修改判断逻辑
        return obj.create_user == request.user

自定义权限的使用方式

  • 全局生效:在 settings.py 的 REST_FRAMEWORK 配置中添加,所有视图默认使用该权限配置
    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': [
            'your_app.permissions.IsEmailVerified',
        ]
    }
    
  • 单视图类生效:在视图类中定义 permission_classes 属性覆盖全局配置
    from your_app.permissions import IsResourceOwner
    from rest_framework.viewsets import ModelViewSet
    
    class ArticleViewSet(ModelViewSet):
        permission_classes = [IsResourceOwner]
        # 其余视图配置省略
    
  • 函数视图生效:使用 @permission_classes 装饰器绑定权限配置
    from rest_framework.decorators import api_view, permission_classes
    
    @api_view(['GET'])
    @permission_classes([IsEmailVerified])
    def get_user_info(request):
        # 业务逻辑省略
    

二、@permission_classes 装饰器底层原理

2.1 装饰器本身的核心逻辑

该装饰器的作用非常简单,就是给被装饰的函数视图绑定一个 permission_classes 属性,存储传入的权限类列表,简化后的源码如下:

def permission_classes(classes):
    def decorator(view_func):
        view_func.permission_classes = classes
        return view_func
    return decorator

2.2 DRF 权限校验的触发逻辑

DRF 处理所有请求时,都会在进入业务逻辑前执行 initial 初始化方法,该方法会按顺序完成身份认证、权限校验、限流校验三步操作,权限校验部分逻辑如下:

  1. 先从当前视图中提取权限类配置:优先读取视图自身的 permission_classes 属性(类视图的类属性、函数视图被装饰器绑定的属性),如果视图没有自定义配置,就读取 settings.py 中的 DEFAULT_PERMISSION_CLASSES 配置作为默认值
  2. 实例化所有权限类,依次调用每个权限类的 has_permission 方法,只要有一个权限类返回 False,直接抛出 403 异常,终止后续流程
  3. 如果当前请求是操作单个资源的请求(比如根据ID查询、修改、删除单条数据),会在 has_permission 全部校验通过后,继续依次调用每个权限类的 has_object_permission 方法,同样只要有一个返回 False 就抛出 403 异常

类视图不需要用装饰器的原因是类本身可以直接定义 permission_classes 类属性,而函数视图无法直接定义类属性,所以需要通过装饰器的方式给函数绑定该属性,DRF 处理类视图和函数视图的权限校验逻辑是完全统一的。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 22:06:02