Django REST Framework如何实现访客可访问单条GET接口、仅管理员可访问列表接口
解决方案
你可以通过DRF ViewSet自带的action属性区分同是GET请求的列表查询和单条查询,提供两种实现方案:
方案1:重写get_permissions方法(更灵活,适合多action权限差异大的场景)
直接在视图类中根据不同的action返回对应权限类,修改后的OrdersViewSet代码如下:
from rest_framework.permissions import IsAuthenticated, IsAdminUser class OrdersViewSet(viewsets.ModelViewSet): serializer_class = OrderSerializer queryset = Order.objects.all() model = Order def get_permissions(self): if self.action == 'list': # 列表接口仅管理员可访问 permission_classes = [IsAdminUser] elif self.action == 'retrieve': # 单条查询支持访客访问,无需权限校验 permission_classes = [] else: # 增删改等其他接口保持原逻辑,仅登录用户可操作 permission_classes = [IsAuthenticated] return [perm() for perm in permission_classes] def update(self, request, *args, **kwargs): kwargs['partial'] = True return super().update(request, *args, **kwargs)
方案2:自定义统一权限类(适合权限逻辑集中管理的场景)
修改你自定义的权限类,在其中增加action判断逻辑:
from rest_framework.permissions import BasePermission, SAFE_METHODS class CustomOrderPermission(BasePermission): def has_permission(self, request, view): # 单条查询所有用户可访问 if view.action == 'retrieve': return True # 列表查询仅管理员可访问 if view.action == 'list': return request.user.is_authenticated and request.user.is_staff # 其他请求需要登录后操作 return request.user.is_authenticated
然后在视图类中指定该权限类即可:
class OrdersViewSet(viewsets.ModelViewSet): permission_classes = [CustomOrderPermission] # 其余原有代码保持不变 serializer_class = OrderSerializer queryset = Order.objects.all() model = Order def update(self, request, *args, **kwargs): kwargs['partial'] = True return super().update(request, *args, **kwargs)
实现原理
DRF的ViewSet在完成路由分发后,会自动给当前视图实例的action属性赋值为当前请求对应的操作名,常见取值包括list/retrieve/create/update/destroy等,因此即使请求方法都是GET,也可以通过view.action明确区分是全量列表查询还是单条资源查询,以此实现精细化的权限控制。
内容的提问来源于stack exchange,提问作者user655941
相关产品推荐
相关产品推荐

