5

Trying to implement djangorestframework_simplejwt in accordance with DRF. After implementing everything based on: https://simpleisbetterthancomplex.com/tutorial/2018/12/19/how-to-use-jwt-authentication-with-django-rest-framework.html and when I'm logged in on localhost:8000, the API Root view is unavailable and the error is an attribute error.

'JWTAuthentication' object has no attribute 'has_permission'

When I view the ModelViewSets themselves, they appear perfectly fine. It's just the API Root itself. When I logout and try to access the API Root, the page loads perfectly fine returning HTTP 403. Am I not supposed to access the API root when logged in or is there a loophole that I can implement (or extend) in views.py?

Edit:

Internal Server Error: /api/
Traceback (most recent call last):
  File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\django\core\handlers\exception.py", line 3
4, in inner
    response = get_response(request)
  File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\django\core\handlers\base.py", line 115, i
n _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\django\core\handlers\base.py", line 113, i
n _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\django\views\decorators\csrf.py", line 54,
 in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\django\views\generic\base.py", line 71, in
 view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\rest_framework\views.py", line 495, in dis
patch
    response = self.handle_exception(exc)
  File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\rest_framework\views.py", line 455, in han
dle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\rest_framework\views.py", line 483, in dis
patch
    self.initial(request, *args, **kwargs)
  File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\rest_framework\views.py", line 401, in ini
tial
    self.check_permissions(request)
  File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\rest_framework\views.py", line 334, in che
ck_permissions
    if not permission.has_permission(request, self):
AttributeError: 'JWTAuthentication' object has no attribute 'has_permission'
[19/Jun/2019 14:52:38] "GET /api/ HTTP/1.1" 500 95529

Here's the views.py:

from django.views.generic import ListView
from rest_framework import viewsets
from .serializers import *
from django_filters import rest_framework as filters
from rest_framework.permissions import IsAuthenticated

class HomePageView(ListView):
    model = Test
    template_name = 'home.html'


class UserViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticated, )
    queryset = User.objects.all()
    serializer_class = UserSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filterset_fields = ('username', 'email')


class TestViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticated, )
    queryset = Test.objects.all()
    serializer_class = TestSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filterset_fields = ('id', 'author')

    def get_queryset(self):
        queryset = Test.objects.all()
        username = self.request.user
        if username is not None:
            queryset = queryset.filter(author__username=username)
        return queryset

and urls.py:

from django.urls import path, include
from rest_framework import routers
from .views import *
from rest_framework_simplejwt import views as jwt_views

router = routers.DefaultRouter()
router.register('users', UserViewSet)
router.register('test', TestViewSet)

urlpatterns = [
    path('', HomePageView.as_view(), name='home'),
    path('api/', include(router.urls)),
    path('api/token/', jwt_views.TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', jwt_views.TokenRefreshView.as_view(), name='token_refresh'),
]
  • Mind posting the relevant block of code where you reference `has_permission`? – Robert Townley Jun 19 '19 at 18:45
  • @RobertTownley is this what you're looking for or the actual views.py? Nvm just added all of it –  Jun 19 '19 at 18:55
  • Hmm that's helpful. Two additional questions: 1) Can you confirm that you installed the JWT library's `DEFAULT_AUTHENTICATION_CLASSES` as described in the tutorial? 2) Does the API root become available again if you remove the two entries in `urls.py` for the `jwt_views`? – Robert Townley Jun 19 '19 at 19:07
  • 1
    Holy. Man, I put it under DEFAULT_PERMISSION_CLASSES... not authentication classes. Thanks! –  Jun 19 '19 at 19:11
  • 1
    Haha easy mistake. Glad it worked, and happy to help! – Robert Townley Jun 19 '19 at 19:16

1 Answers1

7

I had the same issue and solved thanks for the comments. If anyone else is having this issue I'll write it here for you. Most likely an error in your settings be sure to add JWT under Authentication default and not Permission e.g.:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
        
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    )
}
Josh
  • 2,122
  • 1
  • 21
  • 28