7

Full Error: Could not import 'rest_framework_jwt.authentication.JSONWebTokenAuthentication' for API setting 'DEFAULT_AUTHENTICATION_CLASSES'. ImportError: cannot import name 'smart_text' from 'django.utils.encoding'

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
}

And this is the pip freeze in the virtual env:

(backend) PS D:\js\backend> pip freeze                          
asgiref==3.5.1
Django==4.0.4
django-cors-headers==3.11.0
djangorestframework==3.13.1
djangorestframework-jwt==1.11.0
djangorestframework-simplejwt==5.1.0
mysqlclient==2.1.0
PyJWT==1.7.1
pytz==2022.1
sqlparse==0.4.2
tzdata==2022.1

in the middle of the error, it addresses some lines across views.py for decorators:

from http.client import HTTPResponse
from multiprocessing import context
from django.shortcuts import render
from django.http import HttpResponse, Http404, JsonResponse
from .models import Tweet
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import api_view, permission_classes
from rest_framework import status

I'm not sure if they're even related

Good Panic
  • 117
  • 1
  • 1
  • 6

2 Answers2

13

'rest_framework_jwt.authentication.JSONWebTokenAuthentication' this is provided by djangorestframework-jwt wich is not not being maintained anymore . Just uninstall it instead use 'rest_framework_simplejwt.authentication.JWTAuthentication' that comes from djangorestframework-simplejwt

1 - install djangorestframework-simplejwt : pip install djangorestframework-simplejwt

2- Your 'DEFAULT_AUTHENTICATION_CLASSES' should be like this :

'DEFAULT_AUTHENTICATION_CLASSES': (
    
    'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.BasicAuthentication',
    'rest_framework_simplejwt.authentication.JWTAuthentication', 
),

3 - in your root urls.py file (or any other url config), include routes for Simple JWT’s TokenObtainPairView and TokenRefreshView views:

from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
)

urlpatterns = [
    ...
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    ...
]

for more information check the official documentation

monim
  • 3,641
  • 2
  • 10
  • 25
  • 1
    In case anyone else is doing this. its not just as simple as replacing the authentication class. you will have to update your urls for logging in/out/etc as well as any front end pieces that touch those new urls (unless you keep the paths the same) – jAC Sep 18 '22 at 14:51
0

You can override the deprecated parts to use wide spread features in rest_framework_jwt which is not implemented in djangorestframework-simplejwt library.

Specify the authenticator classes to your own path in the settings.py just like this:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'YOUR_AUTH_APP.classes.CustomJSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}

and create a classes.py in YOUR_AUTH_APP to fix the imports:

import django
from django.utils.encoding import smart_str
from django.utils.translation import gettext

django.utils.encoding.smart_text = smart_str # fix deprecated import
django.utils.translation.ugettext = gettext # fix deprecated import
from rest_framework_jwt.authentication import JSONWebTokenAuthentication  # noqa


class CustomJSONWebTokenAuthentication(JSONWebTokenAuthentication):
    def authenticate(self, request):
        tuple_response = super(CustomJSONWebTokenAuthentication, self).authenticate(request)
        return tuple_response

    def authenticate_credentials(self, payload):
        user = super(CustomJSONWebTokenAuthentication, self).authenticate_credentials(payload)
        return user
Salehi
  • 362
  • 2
  • 13