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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 10:17:49