当实现新的身份验证方法并调用具有 IsAuthenticated 权限的视图且用户未通过身份验证时,django rest 框架会引发:
File "XXX/site-packages/rest_framework/views.py", line 206, in check_permissions
self.permission_denied(request)
File "XXX/site-packages/rest_framework/views.py", line 80, in permission_denied
if not self.request.successful_authenticator:
File "XXX/site-packages/rest_framework/request.py", line 362, in __getattr__
return getattr(self._request, attr)
AttributeError: 'WSGIRequest' object has no attribute 'successful_authenticator'
看过代码,觉得不对。 “ self.request
.successful_authenticator”在哪里,我认为应该是“ request
.successful_authenticator”。
Views.py,第 80 行附近。
def permission_denied(self, request):
"""
If request is not permitted, determine what kind of exception to raise.
"""
if not self.request.successful_authenticator:
raise exceptions.NotAuthenticated()
raise exceptions.PermissionDenied()
对不起,我在我的代码中犯了同样的错误!!!
对于通过 Google 解决此问题的任何其他人...
错误来源的线索是它说WSGIRequest
没有属性successful_authenticator
。 但是此时在 DRF 代码中,我们应该处理rest_framework.request.Request
而不是裸WSGIRequest
。
事实上,如果你通过 pdb 进入代码,你可能会发现你确实有一个 DRF 请求,而不是一个空的 WSGIRequest。
问题是request.Request
有许多@property
装饰方法(例如user
, successful_authenticator
等)但也有一个__getattr__
方法。
发生的情况是:如果任何属性中的代码触发了AttributeError
那么 Python 将调用__getattr__
方法,该方法最终会尝试找到一个 attr(与该属性具有相同的名称)错误)在子WSGIRequest
对象上。
这就是您如何得到'WSGIRequest' object has no attribute 'successful_authenticator'
或'WSGIRequest' object has no attribute 'user'
(当然,后者仅当您不使用 Django AuthenticationMiddleware 时)。
在我的情况下, AttributeError 来自我的authentication_classes
... 之一,在您第一次访问@successful_authenticator
属性时依次调用。 Request 类上的属性和__getattr__
的组合有效地掩盖了错误的真正来源。
当我们的 DRF 视图有不正确的authentication_classes
(意外地,另一个rest api 框架的遗留身份验证类)时遇到它。 希望有一天 python 成为类型安全的 :)
仅供参考,如果您在djangorestframework-expiring-authtoken
< 0.1.4
使用 DRF,那么您将看到此错误,由以下问题引起:
https://github.com/JamesRitchie/django-rest-framework-expiring-tokens/issues/11
最有用的评论
对于通过 Google 解决此问题的任何其他人...
错误来源的线索是它说
WSGIRequest
没有属性successful_authenticator
。 但是此时在 DRF 代码中,我们应该处理rest_framework.request.Request
而不是裸WSGIRequest
。事实上,如果你通过 pdb 进入代码,你可能会发现你确实有一个 DRF 请求,而不是一个空的 WSGIRequest。
问题是
request.Request
有许多@property
装饰方法(例如user
,successful_authenticator
等)但也有一个__getattr__
方法。发生的情况是:如果任何属性中的代码触发了
AttributeError
那么 Python 将调用__getattr__
方法,该方法最终会尝试找到一个 attr(与该属性具有相同的名称)错误)在子WSGIRequest
对象上。这就是您如何得到
'WSGIRequest' object has no attribute 'successful_authenticator'
或'WSGIRequest' object has no attribute 'user'
(当然,后者仅当您不使用 Django AuthenticationMiddleware 时)。在我的情况下, AttributeError 来自我的
authentication_classes
... 之一,在您第一次访问@successful_authenticator
属性时依次调用。 Request 类上的属性和__getattr__
的组合有效地掩盖了错误的真正来源。