如何在Django REST Framework的单个视图中只为POST方法添加IsAuthenticated权限校验,GET方法无需认证?
解决单个视图中仅POST方法需认证的问题
嘿,刚好碰到过类似的需求!你想要在同一个products_list视图里,让GET方法允许匿名访问,只有POST方法强制用户认证,还不能拆分视图,对吧?这里有两种实用的解决方案:
方法一:在POST分支手动校验认证状态
这种方法直接在POST请求的处理逻辑里加入认证检查,简单直接,适合快速实现:
from rest_framework.permissions import IsAuthenticated from rest_framework.exceptions import PermissionDenied from rest_framework import status, Response from .models import Product from .serializers import ProductSerializer @api_view(['GET', 'POST']) def products_list(request): """ 获取所有产品列表,或创建新的产品。 """ if request.method == 'GET': products = Product.objects.all() serializer = ProductSerializer(products, many=True) return Response(serializer.data) elif request.method == 'POST': # 手动实例化IsAuthenticated权限类并检查权限 auth_permission = IsAuthenticated() if not auth_permission.has_permission(request, None): raise PermissionDenied("你需要登录才能创建产品") serializer = ProductSerializer(data=request.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)
方法二:自定义权限类(推荐)
这种方法更符合Django REST Framework的设计规范,代码更整洁,扩展性也更强——如果以后要调整其他方法的权限,直接修改权限类即可:
第一步:定义自定义权限类
在你的app里新建permissions.py(或者直接放在视图文件里):
from rest_framework.permissions import BasePermission, IsAuthenticated class PostOnlyAuthenticated(BasePermission): """仅POST方法要求用户认证,其他方法允许匿名访问""" def has_permission(self, request, view): # GET方法直接放行 if request.method == 'GET': return True # POST方法使用IsAuthenticated的校验逻辑 return IsAuthenticated().has_permission(request, view)
第二步:将权限类应用到视图
from rest_framework import status, Response from rest_framework.decorators import api_view, permission_classes from .models import Product from .serializers import ProductSerializer from .permissions import PostOnlyAuthenticated # 导入自定义权限类 @api_view(['GET', 'POST']) @permission_classes([PostOnlyAuthenticated]) def products_list(request): """ 获取所有产品列表,或创建新的产品。 """ if request.method == 'GET': products = Product.objects.all() serializer = ProductSerializer(products, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = ProductSerializer(data=request.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)
两种方法都能实现你的需求,个人更推荐第二种,因为它遵循了DRF的权限系统设计,代码更易维护,也更符合最佳实践。
内容的提问来源于stack exchange,提问作者Funeral
相关产品推荐
相关产品推荐

