Django-rest-framework: Error 'WSGIRequest' object has no attribute 'successful_authenticator'

Created on 6 Jun 2013  ·  4Comments  ·  Source: encode/django-rest-framework

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()

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 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.

All 4 comments

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

Was this page helpful?
0 / 5 - 0 ratings