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

如何在Django REST Framework中配置符合特定规则的对象权限?

解决方案:自定义DRF权限类

首先,确实没有现成的DRF标准权限类完全匹配你的需求——IsAdminUser会限制所有操作必须是管理员,而IsAuthenticatedOrReadOnly虽然允许认证用户写操作,但没法区分PUT/DELETE和PATCH/POST的权限差异。

最优方案是在DRF中自定义权限类,因为DRF的权限系统可以直接绑定到视图,并且能精细控制每个HTTP方法的权限,比在Django模型层控制更灵活(模型层的权限是基于add/change/delete这些动作,没法区分PUT和PATCH这种同属change动作但权限不同的场景)。

步骤1:创建自定义权限类

在你的项目中新建(或修改)permissions.py文件,添加以下代码:

from rest_framework import permissions

class ProductPermission(permissions.BasePermission):
    def has_permission(self, request, view):
        # 所有请求都要求用户已认证(对应你表格里的所有端点都需要认证)
        if not request.user.is_authenticated:
            return False
        
        # 对于PUT和DELETE方法,仅允许管理员执行
        if request.method in ['PUT', 'DELETE']:
            return request.user.is_staff
        
        # 其他方法(GET、POST、PATCH)允许所有已认证用户执行
        return True

步骤2:在视图中应用自定义权限

修改你的views.py,把permission_classes替换成我们刚写的自定义类:

from rest_framework import viewsets, authentication, permissions
from .models import Product
from .serializers import ProductSerializer
from .permissions import ProductPermission  # 导入自定义权限类

class ProductView(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    authentication_classes = [authentication.SessionAuthentication, authentication.TokenAuthentication]
    permission_classes = (ProductPermission,)  # 替换为自定义权限

验证权限规则

现在这个配置完全匹配你的需求:

  • GET /products、GET /products/{pk}:所有已认证用户可访问,返回产品列表/详情
  • POST /products:所有已认证用户可创建产品
  • PUT /products/{pk}:仅管理员可完全更新产品
  • PATCH /products/{pk}:所有已认证用户可部分更新产品
  • DELETE /products/{pk}:仅管理员可删除产品

为什么不选模型层控制?

Django的模型权限(比如django.contrib.auth里的权限)是基于模型的动作(add_product、change_product、delete_product),但PUT和PATCH都属于change_product动作,没法单独区分这两个方法的权限。而DRF的自定义权限类可以直接判断请求的HTTP方法,刚好能满足你这种精细的权限划分需求,所以是最优选择。

内容的提问来源于stack exchange,提问作者Jaco

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 16:22:27