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

Django REST Framework的@action接口返回403而非405问题排查

根本原因

DRF默认的请求处理流程顺序为:

  1. 路由匹配对应视图类
  2. 执行用户认证逻辑
  3. 执行权限校验逻辑
  4. 匹配请求方法对应的视图方法、校验请求方法是否在允许范围内,该步骤才会为view.action赋值,若方法不允许则返回405状态码

因此当POST请求访问仅支持GET方法的logout接口时,权限校验先于方法校验执行,此时view.action尚未赋值,自然就会返回403而非预期的405。

解决方案
  • 方案1:重写视图集的initial方法,调整校验顺序
    将请求方法匹配和校验逻辑提前到权限校验之前执行,代码示例:
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.viewsets import ModelViewSet

class UsersViewSet(ModelViewSet):
    # 原有视图逻辑保持不变
    def initial(self, request, *args, **kwargs):
        # 提前匹配请求对应的action
        self.action = self.action_map.get(request.method.lower())
        if not self.action:
            raise MethodNotAllowed(request.method)
        # 执行原有的认证、权限、节流校验逻辑
        super().initial(request, *args, **kwargs)

该方案无需修改原有权限逻辑,方法不允许时会直接返回405,符合预期。

  • 方案2:修改自定义权限类逻辑
    在UsersPermissions权限类的校验逻辑开头,新增action为空的判断,直接抛出方法不允许异常,代码示例:
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.permissions import BasePermission

class UsersPermissions(BasePermission):
    def has_permission(self, request, view):
        if view.action is None:
            raise MethodNotAllowed(request.method)
        # 原有权限校验逻辑保持不变
        ...
  • 方案3:校验请求路径是否匹配
    当前通过DefaultRouter注册的users视图集,生成的logout接口路径为/users/logout/,若直接请求/logout/会匹配不到对应action规则,DRF会尝试匹配其他路由,也会导致异常状态码返回,需确保请求路径和路由生成的路径一致。如果需要logout接口直接在根路径,可单独在urlpatterns中添加独立路由配置,限制允许的请求方法即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 00:15:01