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

DRF ViewSet执行动作多次且GET请求action为None求助

DRF ViewSet动作重复执行及action为None异常分析与解决

问题概述

使用Django REST Framework的ViewSet实现list、create等动作,发送GET请求时出现部分动作重复执行,且self.action有时为None。移除DjangoModelPermissions后,action为None的现象消失,但仍未明确问题根源及解决办法。

原因分析

1. action为None的根源

DjangoModelPermissions的权限检查逻辑会主动调用view.get_queryset(),而此时DRF还未完成路由到动作的映射(即self.action尚未被赋值),因此在get_queryset中会捕获到action为None的情况。

2. 动作重复执行的原因

  • get_queryset被多次调用:权限检查阶段(如DjangoModelPermissions触发)会调用一次,视图处理逻辑执行时又会调用一次,导致控制台重复输出动作名称。
  • 原代码逻辑过度依赖action判断查询集,当action为None时会进入错误分支,可能触发额外的查询或逻辑执行,加剧重复现象。

解决方案

1. 重构get_queryset,摆脱对action的依赖

优先通过路由参数(而非action)判断返回的查询集,避免action未赋值时的逻辑错误:

def get_queryset(self):
    print(self.action)
    pk = self.kwargs.get("pk")
    questionnaire_id = self.kwargs.get("questionnaire_id")
    
    if pk:
        return Question.objects.filter(pk=pk)
    elif questionnaire_id:
        return Question.objects.filter(questionnaire=questionnaire_id)
    # 兜底逻辑,根据业务需求调整
    return Question.objects.none()

2. 优化权限配置,避免不必要的DjangoModelPermissions调用

调整get_permissions逻辑,确保DjangoModelPermissions仅在需要的动作中使用:

def get_permissions(self):
    # 仅对需要模型权限的动作使用DjangoModelPermissions
    if self.action in ["create", "update", "partial_update", "destroy"]:
        permission_classes = [DjangoModelPermissions]
    else:
        permission_classes = [IsStaffDoctorOrIsStaffHumanResource]
    return [permission() for permission in permission_classes]

注意:使用DjangoModelPermissions时,需确保用户拥有对应模型的权限(如add_question、change_question等),否则会导致权限校验失败。

3. 排查请求重复问题

检查前端是否存在重复发送请求的情况,或服务器是否有重定向、中间件触发额外请求的逻辑,这也可能导致动作重复执行。

验证效果

修改后重新测试,self.action为None的现象会消失,get_queryset的调用次数会恢复正常(单次请求对应必要的调用次数)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 17:53:12