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

Django PUT端点认证报错:wrapped_view()缺少必需的位置参数'request'排查求助

问题:Django视图认证装饰器报错wrapped_view() missing 1 required positional argument: 'request'

我正在尝试创建一个用于编辑帖子数据的PUT端点,该端点通过URL传入帖子ID,随后将新的帖子数据写入对应实体。目前遇到的问题是,请求无法传递至认证器中(我使用Cognito进行身份验证,这一点对当前错误而言并非关键)。尽管已明确传入数据,但cognito_authenticator函数中的wrapped_view始终无法获取到request参数,报错信息为:

"wrapped_view() missing 1 required positional argument: 'request'"

相关代码

Test.py

def test_edit(self):
    response = self.client.put(reverse('edit_post_by_id', kwargs={'post_id': str(self.post.uuid)}), data={'body': 'updated text #update'}, content_type='application/json', **{'HTTP_AUTHORIZATION': f'bearer {self.cognito.access_token}'})
    self.assertEqual(response.status_code, status.HTTP_200_OK)

View.py

@api_view(['PUT'])
@method_decorator(cognito_authenticator)
def edit_post(request, post_id):
    try:
        post = Post.objects.get(pk=post_id)
    except Post.DoesNotExist:
        return JsonResponse(dict(error=f'Post id: {post_id} does not exists'), status=status.HTTP_400_BAD_REQUEST)

认证器代码

def cognito_authenticator(view_func=None):
    if view_func is None:
        return partial(cognito_authenticator)
    @wraps(view_func)
    def wrapped_view(request, *args, **kwargs):
        # Check the cognito token from the request.
        auth = request.headers.get("Authorization", None)
        if not auth:
            return Response(dict(error='Authorization header expected'), status=status.HTTP_401_UNAUTHORIZED)
        parts = auth.split()
        if parts[0].lower() != "bearer":
            return Response(dict(error='Authorization header must start with bearer'), status=status.HTTP_401_UNAUTHORIZED)
        elif len(parts) == 1:
            return Response(dict(error='Token not found'), status=status.HTTP_401_UNAUTHORIZED)
        elif len(parts) > 2:
            return Response(dict(error='Authorization header must be Bearer token'), status=status.HTTP_401_UNAUTHORIZED)
        token = parts[1]
        try:
            res = decode_cognito_jwt(token)
        except Exception:
            # Fail if invalid
            return Response("Invalid JWT", status=status.HTTP_401_UNAUTHORIZED) # Or HttpResponseForbidden()
        else:
            # Proceed with the view if valid
            return view_func(request, *args, **kwargs)
    return wrapped_view

解决方案

我来帮你分析下这个问题的根源:你误用了method_decorator!

method_decorator是Django专门为基于类的视图设计的工具,它的作用是把普通的函数装饰器转换成能适配类方法的形式(类方法的第一个参数是self而不是request)。但你的edit_post是一个基于函数的视图,直接给它套method_decorator会打乱参数传递的逻辑,导致request无法正确传入wrapped_view,才会报缺少参数的错误。

修复步骤非常简单:

直接移除@method_decorator,把@cognito_authenticator直接应用在函数视图上就行——你的认证装饰器已经是标准的函数视图装饰器,完全不需要额外适配。

修改后的View.py代码:

@api_view(['PUT'])
@cognito_authenticator  # 去掉method_decorator,直接使用装饰器
def edit_post(request, post_id):
    try:
        post = Post.objects.get(pk=post_id)
    except Post.DoesNotExist:
        return JsonResponse(dict(error=f'Post id: {post_id} does not exists'), status=status.HTTP_400_BAD_REQUEST)
    # 这里可以补充你的帖子更新逻辑

额外说明

如果之后你需要在类视图上使用这个认证装饰器,那时候才需要用到method_decorator,用法示例如下:

from django.views import View
from django.utils.decorators import method_decorator

@method_decorator(cognito_authenticator, name='dispatch')
class EditPostView(View):
    def put(self, request, post_id):
        # 类视图的PUT方法逻辑
        pass

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 13:12:28