When a implement a new authentication method and call a view with IsAuthenticated permission and user not is authenticated, django rest framework raises:
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'
Seen code, I think is incorrect. Where is "self.request
.successful_authenticator" I think should be "request
.successful_authenticator".
Views.py, near line 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()
Sorry, I made same mistakes in my code!!!
For anyone else arriving at this issue via Google...
The clue to the source of the error is that it says WSGIRequest
has no attribute successful_authenticator
. But at this point in the DRF code we should be dealing with a rest_framework.request.Request
rather than a bare WSGIRequest
.
And in fact if you drop into the code via pdb you'll probably find you do have a DRF request rather than a bare WSGIRequest.
The problem is that request.Request
has a number of @property
decorated methods (such as user
, successful_authenticator
and others) but also has a __getattr__
method.
What happens is: if the code in any of the properties triggers an AttributeError
then Python will call the __getattr__
method instead, which ultimately tries to find an attr (with the same name as the property which errored) on the child WSGIRequest
object.
Which is how you get errors like 'WSGIRequest' object has no attribute 'successful_authenticator'
or 'WSGIRequest' object has no attribute 'user'
(the latter only if you don't use Django AuthenticationMiddleware of course).
In my case the AttributeError came from one of my authentication_classes
... which are called in turn the first time you access the @successful_authenticator
property. The combination of properties and __getattr__
on the Request class effectively masks the true source of the error.
Run into it when our DRF view had improper authentication_classes
(accidentally, legacy auth classes for another rest api framework). Hope one day python become typesafe :)
FYI, if you're using DRF with djangorestframework-expiring-authtoken
< 0.1.4
then you will see this error, caused by the following issue:
https://github.com/JamesRitchie/django-rest-framework-expiring-tokens/issues/11
Most helpful comment
For anyone else arriving at this issue via Google...
The clue to the source of the error is that it says
WSGIRequest
has no attributesuccessful_authenticator
. But at this point in the DRF code we should be dealing with arest_framework.request.Request
rather than a bareWSGIRequest
.And in fact if you drop into the code via pdb you'll probably find you do have a DRF request rather than a bare WSGIRequest.
The problem is that
request.Request
has a number of@property
decorated methods (such asuser
,successful_authenticator
and others) but also has a__getattr__
method.What happens is: if the code in any of the properties triggers an
AttributeError
then Python will call the__getattr__
method instead, which ultimately tries to find an attr (with the same name as the property which errored) on the childWSGIRequest
object.Which is how you get errors like
'WSGIRequest' object has no attribute 'successful_authenticator'
or'WSGIRequest' object has no attribute 'user'
(the latter only if you don't use Django AuthenticationMiddleware of course).In my case the AttributeError came from one of my
authentication_classes
... which are called in turn the first time you access the@successful_authenticator
property. The combination of properties and__getattr__
on the Request class effectively masks the true source of the error.