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
相关产品推荐
相关产品推荐

