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

Django基于用户角色和client_id实现自定义权限控制的咨询

实现步骤说明

1. 明确权限类的使用场景

你提到的 BasePermission 是Django REST Framework提供的视图层权限校验工具,不需要在模型层使用,直接绑定到对应业务视图上即可,请求进入视图前会自动执行校验逻辑。

2. 先封装通用工具方法

基于你现有的模型结构,先封装两个快速获取用户属性的工具方法,避免后续重复写查询逻辑:

# 可放在项目的utils.py文件中
from .models import UserCustomModel, ClientUser

def get_user_role(user):
    """获取用户角色"""
    try:
        return user.usercustommodel.roles
    except UserCustomModel.DoesNotExist:
        return None

def get_user_client(user):
    """获取用户所属客户,你现有中间表配置了user为主键,所以每个用户只会有一条有效记录"""
    try:
        # 注意你的deleted字段默认值为1代表有效,如果实际是0代表有效请修改判断条件
        return ClientUser.objects.get(user=user, deleted=1).client
    except ClientUser.DoesNotExist:
        return None

3. 编写符合业务规则的自定义权限类

需要同时实现has_permission(全局访问权限校验)和has_object_permission(单对象操作权限校验)两个方法,覆盖你要求的所有规则:

from rest_framework.permissions import BasePermission

class UserManagePermission(BasePermission):
    # 定义角色层级,数值越大权限越高
    ROLE_LEVEL = {
        'READER': 1,
        'CONTRIBUTOR': 2,
        'SUPERUSER': 3,
        'ADMIN': 4
    }

    def has_permission(self, request, view):
        # 先校验当前用户有没有用户管理的全局访问权限
        current_role = get_user_role(request.user)
        return current_role in ['SUPERUSER', 'ADMIN']

    def has_object_permission(self, request, view, obj):
        # obj为当前要操作的目标用户对象
        current_user = request.user
        current_role = get_user_role(current_user)
        current_client = get_user_client(current_user)
        target_client = get_user_client(obj)
        target_role = get_user_role(obj)

        # 非有效数据直接拒绝
        if not all([current_client, target_client, target_role]):
            return False
        # 校验同客户限制
        if current_client.client_id != target_client.client_id:
            return False
        # 校验角色操作权限
        if current_role == 'ADMIN':
            # ADMIN可操作所有权限低于自己的用户
            return self.ROLE_LEVEL[target_role] < self.ROLE_LEVEL[current_role]
        if current_role == 'SUPERUSER':
            # SUPERUSER仅可操作 CONTRIBUTOR、READER
            return self.ROLE_LEVEL[target_role] <= 2
        return False

4. 在视图层绑定权限类

以DRF的ModelViewSet为例,直接将权限类加到视图的permission_classes属性中即可:

from rest_framework.viewsets import ModelViewSet
from django.contrib.auth.models import User
from .serializers import UserSerializer

class UserManageViewSet(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    # 绑定自定义权限类
    permission_classes = [UserManagePermission]

    # 额外补充:列表查询时主动过滤同客户用户,不要依赖权限类做列表过滤
    def get_queryset(self):
        current_client = get_user_client(self.request.user)
        if not current_client:
            return User.objects.none()
        return User.objects.filter(
            clientuser__client=current_client,
            clientuser__deleted=1,
            usercustommodel__deleted=1
        )

其他场景适配

如果你用的是Django原生后台而非DRF接口,只需重写对应ModelAdmin的has_add_permission、has_change_permission、has_delete_permission方法,逻辑和上面的权限类完全一致即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 07:39:05