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:新增对象权限控制(体验更友好)
如果需要给用户返回明确的权限不足提示,推荐自定义权限类实现控制,逻辑更清晰:
- 定义权限类
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
- 在ViewSet中注册权限类
class PurchaseViewSet(viewsets.ModelViewSet): queryset = Purchases.objects.all() serializer_class = PurchaseSerializer # 注册自定义权限类,可搭配其他全局权限使用 permission_classes = [permissions.IsAuthenticated, PurchaseOperatePermission] # 其他原有逻辑...
该方案下,用户操作已审批的采购单时会返回403 Forbidden,可搭配自定义错误信息提示用户「已审批的采购单不可修改或删除」。
内容的提问来源于stack exchange,提问作者afonso
相关产品推荐
相关产品推荐

