Django Rest Framework通过关联模型实现权限控制的方案咨询
方案结论
你提到的第二种自定义权限类的方案是DRF生态下处理关联对象权限的成熟标准实现,不存在根本性问题,完全符合你要求的「Study作为权限唯一可信来源」的要求,不需要冗余的权限同步逻辑。
实现示例
1. 自定义关联权限校验类
from rest_framework.permissions import BasePermission class RelatedStudyAccessPermission(BasePermission): """校验用户对Result关联的Study是否有访问权限""" def has_permission(self, request, view): # 所有请求需先登录,列表页的权限过滤后续在queryset层处理 return request.user.is_authenticated def has_object_permission(self, request, view, obj): # 直接复用Study的权限校验逻辑,此处按你实际的Study权限规则修改即可 # 示例1:使用Django自带对象权限/ django-guardian 校验查看权限 return request.user.has_perm("你的应用名.view_study", obj.study) # 示例2:如果Study有members多对多字段关联授权用户,替换为: # return obj.study.members.filter(id=request.user.id).exists()
2. Result视图层配置
需要同时配置权限类、重写查询集过滤,避免无权限用户在列表接口看到所有Result数据:
from rest_framework import viewsets from .models import Result, Study from .serializers import ResultSerializer from .permissions import RelatedStudyAccessPermission class ResultViewSet(viewsets.ModelViewSet): serializer_class = ResultSerializer permission_classes = [RelatedStudyAccessPermission] def get_queryset(self): # 仅返回用户有权限访问的Study对应的Result # 对应上面权限校验的两种写法,二选一即可 # 写法1:适配django-guardian/自带对象权限的过滤 accessible_studies = Study.objects.filter( user_permissions__user=self.request.user, user_permissions__codename="view_study" ) # 写法2:适配Study.members多对多授权的过滤 # accessible_studies = self.request.user.study_set.all() return Result.objects.filter(study__in=accessible_studies)
补充说明
如果使用django-guardian这类成熟的第三方对象权限组件,还可以直接使用它提供的DjangoObjectPermissionsFilter等过滤类,无需手动编写查询集过滤逻辑,进一步减少重复代码。
内容的提问来源于stack exchange,提问作者Andrew Guenther
相关产品推荐
相关产品推荐

