Django REST Framework中为不同HTTP方法设置独立权限类
解决方案:给不同HTTP方法设置差异化权限
要实现「GET仅允许认证用户访问,POST允许游客+认证用户访问」的需求,有两种实用方案,直接给你代码和说明:
方案一:重写视图的get_permissions方法(灵活适配单个视图)
这种方式无需额外定义权限类,直接在视图内针对每个HTTP方法指定权限规则:
from rest_framework import permissions, status from rest_framework.response import Response from rest_framework.views import APIView from .models import ServiceSupplier from .serializers import ServiceSupplierSerializer class ServiceSupplierApiView(APIView): def get_permissions(self): # 根据请求方法返回对应权限列表 if self.request.method == 'GET': # GET请求仅开放给认证用户 return [permissions.IsAuthenticated()] elif self.request.method == 'POST': # POST请求允许所有用户(游客+认证用户) return [permissions.AllowAny()] # PUT、DELETE等其他方法默认要求认证,可按需调整 return [permissions.IsAuthenticated()] def get(self, request, *args, **kwargs): lista = ServiceSupplier.objects.all() serializer = ServiceSupplierSerializer(lista, many=True) return Response(serializer.data, status=status.HTTP_200_OK) def post(self, request, *args, **kwargs): data = { 'name': request.data.get('name'), } serializer = ServiceSupplierSerializer(data=data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def put(self, request, *args, **kwargs): # 注意:原代码中使用的Supplier应为ServiceSupplier try: instance = ServiceSupplier.objects.get(id=request.data.get('id')) except ServiceSupplier.DoesNotExist: return Response({"res": "Object with id does not exist"}, status=status.HTTP_404_NOT_FOUND) data = { 'name': request.data.get('name'), } serializer = ServiceSupplierSerializer(instance=instance, data=data, partial=True) if serializer.is_valid(): serializer.save() # PUT更新成功用200 OK更规范,而非201 return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, id, *args, **kwargs): try: instance = ServiceSupplier.objects.get(id=id) except ServiceSupplier.DoesNotExist: return Response({"res": "Object with id does not exist"}, status=status.HTTP_404_NOT_FOUND) instance.delete() return Response({"res": "Object deleted!"}, status=status.HTTP_200_OK)
说明
get_permissions方法会在每个请求到达时触发,返回当前请求对应的权限类实例列表- 可自由扩展其他方法的权限规则,比如限制PUT/DELETE仅允许管理员操作
方案二:自定义权限类(适合多视图复用相同规则)
如果多个视图都需要「POST允许游客,其他方法要求认证」的规则,可自定义通用权限类:
from rest_framework import permissions class IsAuthenticatedOrPostAllowAny(permissions.BasePermission): def has_permission(self, request, view): # POST请求直接放行 if request.method == 'POST': return True # 其他方法要求用户已认证 return request.user and request.user.is_authenticated
然后在视图中直接使用该权限类:
class ServiceSupplierApiView(APIView): permission_classes = [IsAuthenticatedOrPostAllowAny] # 以下get/post/put/delete方法保持不变(记得修正原代码中的小问题)
说明
- 自定义权限类继承自
permissions.BasePermission,只需实现has_permission方法即可 - 该类可在多个视图中复用,减少重复代码
内容的提问来源于stack exchange,提问作者Jesse Cassule
相关产品推荐
相关产品推荐

