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

Django ViewSet限制仅状态为VA的Purchases可更新删除功能失效如何解决

问题原因与解决方案

核心问题点

  • QuerySet过滤结果未赋值:Django ORM的filter()方法不会修改原QuerySet对象,而是返回全新的过滤后实例,原代码未接收过滤结果,相当于过滤逻辑完全未生效。
  • 动作名称拼写错误:DRF ViewSet的部分更新动作名为partial_update,原代码写为parcial_update,缺失字母t,导致部分更新请求未命中过滤逻辑。
  • 删除动作名称错误:DRF ViewSet默认的删除动作是destroy而非delete,原代码判断条件不包含正确的删除动作名,删除操作不受控制。
  • 过滤条件写法不规范:硬编码状态值"VA"不如直接引用模型常量更易维护,且filter内应该用关键字参数而非判断表达式。

修正方案

方案1:修正get_queryset方法

直接修正原方法的错误即可实现基础控制:

def get_queryset(self):
    qs = super().get_queryset()
    # 修正动作名、赋值过滤结果、使用模型常量避免硬编码
    if self.action in ("update", "partial_update", "destroy"):
        qs = qs.filter(status=Purchases.EM_VALIDACAO)
    return qs

该方案实现效果为:用户试图操作已审批的采购单时,接口会返回404 Not Found。

方案2:新增对象权限控制(体验更友好)

如果需要给用户返回明确的权限不足提示,推荐自定义权限类实现控制,逻辑更清晰:

  1. 定义权限类
from rest_framework import permissions

class PurchaseOperatePermission(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        #  GET/HEAD/OPTIONS等读请求直接放行
        if request.method in permissions.SAFE_METHODS:
            return True
        # 写请求仅允许状态为待验证的采购单
        return obj.status == Purchases.EM_VALIDACAO
  1. 在ViewSet中注册权限类
class PurchaseViewSet(viewsets.ModelViewSet):
    queryset = Purchases.objects.all()
    serializer_class = PurchaseSerializer
    # 注册自定义权限类,可搭配其他全局权限使用
    permission_classes = [permissions.IsAuthenticated, PurchaseOperatePermission]
    
    # 其他原有逻辑...

该方案下,用户操作已审批的采购单时会返回403 Forbidden,可搭配自定义错误信息提示用户「已审批的采购单不可修改或删除」。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 14:36:05