Django REST ModelViewSet自定义权限:普通用户仅可操作所属物料
实现方案
推荐使用Django REST Framework自带的自定义权限类实现需求,相比重写每个视图方法的逻辑,权限和业务分离的方案可维护性更高。
1. 定义自定义权限类
from rest_framework.permissions import BasePermission # 你原有的admin判断逻辑 def app_admin(user): if user.user_is_admin: return True if user.is_superuser: return True return False class MaterialPermission(BasePermission): # 全局权限校验,控制是否可访问视图 def has_permission(self, request, view): # 未登录用户直接拒绝 if not request.user.is_authenticated: return False # 管理员直接放行所有操作 if app_admin(request.user): return True # 普通用户允许访问的动作,可根据需求调整 allowed_actions = ['list', 'retrieve', 'create', 'destroy'] return view.action in allowed_actions # 对象级权限校验,控制是否可操作单条具体记录 def has_object_permission(self, request, view, obj): if app_admin(request.user): return True # 校验当前用户是否和目标material有关联关系 return UserMaterialAllow.objects.filter( user=request.user, material=obj ).exists()
2. 调整MaterialView配置
class MaterialView(viewsets.ModelViewSet): queryset = Material.objects.all() # 注意你原来的代码里是横线,要改成下划线的serializer_class serializer_class = MaterialSerializer # 绑定自定义权限类 permission_classes = [MaterialPermission] # 重写查询集,普通用户仅能看到自己关联的Material def get_queryset(self): origin_queryset = super().get_queryset() user = self.request.user if app_admin(user): return origin_queryset return origin_queryset.filter(usermaterialallow__user=user) # 可选:普通用户创建Material时自动建立关联关系,根据你的业务逻辑调整 def perform_create(self, serializer): material = serializer.save() if not app_admin(self.request.user): UserMaterialAllow.objects.get_or_create( user=self.request.user, material=material )
注意事项
- 如果你的业务规则要求普通用户只能创建已经关联过权限的Material,可以在
perform_create中添加校验,不符合规则直接返回403 - 如果不需要自动创建关联关系,直接删除
perform_create方法即可 - 对象级权限默认不会对list接口生效,所以必须重写
get_queryset做过滤,避免普通用户看到其他用户的Material
内容的提问来源于stack exchange,提问作者ira
相关产品推荐
相关产品推荐

