DRF项目中/api/v1/invoice/#id/接口权限控制配置咨询
结论
现有配置不能完整实现需求,存在的问题和调整方案如下:
存在的问题
1. 对象权限校验未触发
DRF 原生的APIView不会自动执行对象级权限校验,你当前的视图中拿到invoice对象后没有手动调用check_object_permissions(request, invoice),导致自定义的has_object_permission方法完全不生效,所有登录用户都能查看任意发票,权限控制完全失效。
2. 缺少更新、删除操作的接口实现
当前视图只写了GET方法,没有实现PUT/PATCH/DELETE的处理逻辑,哪怕权限逻辑正确,超级用户也无法执行更新、删除操作,不符合第二条规则要求。
3. 单对象查询未做异常捕获
直接用Invoice.objects.get()查询不存在的发票ID时会抛出DoesNotExist异常,直接返回500错误,不符合REST规范,应该返回404状态码。
4. 可选适配:路径匹配问题
你需求里的接口路径是/api/v1/invoice/#id/,当前urls配置的是v1/invoices/<str:invoice_id>/,注意单复数(invoice/invoices)的差异,如果你全局urls没有加api/前缀的话,路径也会对不上。
调整方案
方案1:保留APIView写法,修复现有问题
from django.shortcuts import get_object_or_404 class InvoiceDisplayView(APIView): permission_classes = [AuthorGetStaffGetAdminAll] def get(self, request, invoice_id): # 用get_object_or_404替换原生get,不存在直接返回404 invoice = get_object_or_404(Invoice, id__iexact=invoice_id) # 手动触发对象权限校验 self.check_object_permissions(request, invoice) serializer = InvoiceSerializer(invoice) return Response(serializer.data)
如果需要支持更新删除,按照相同逻辑补充put/patch/delete方法即可。
方案2:改用DRF通用视图,简化代码
直接使用RetrieveUpdateDestroyAPIView,会自动处理对象查询、权限校验、各方法的基础逻辑,不需要手动写重复代码:
from rest_framework.generics import RetrieveUpdateDestroyAPIView class InvoiceDisplayView(RetrieveUpdateDestroyAPIView): permission_classes = [AuthorGetStaffGetAdminAll] serializer_class = InvoiceSerializer queryset = Invoice.objects.all() lookup_field = 'id' lookup_url_kwarg = 'invoice_id' # 自动支持GET/ PUT/ PATCH/ DELETE所有操作
补充说明
你写的AuthorGetStaffGetAdminAll权限逻辑本身是符合需求的:
- 超级用户所有操作都放行
- 作者、staff身份用户仅放行GET/HEAD/OPTIONS这类非编辑操作
- 未登录用户直接拦截
不需要修改权限类本身的代码。
内容的提问来源于stack exchange,提问作者Rajesh
相关产品推荐
相关产品推荐

