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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 10:06:03