Как настроить сообщение для неактивного пользователя в Djoser?

Я работаю над проектом Django и использую Djoser в качестве библиотеки auth. Однако, когда пользователь пытается создать jwt-токен, он возвращает

{
    "detail": "No active account found with the given credentials"
}

для случаев, когда нет пользователя с учетными данными и когда есть пользователь, который неактивен. После некоторых исследований, я нашел часть кода ниже, который был использован для переопределения TokenObtain в библиотеке simplejwt, на основе которой был написан Djoser, но я не знаю, как на самом деле это сделать. Я довольно новичок в Djoser.

from rest_framework import status, exceptions
from django.utils.translation import gettext_lazy as _
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer, TokenObtainSerializer


class CustomTokenObtainPairSerializer(TokenObtainPairSerializer, TokenObtainSerializer):
    
  
    # Overiding validate function in the TokenObtainSerializer  
    def validate(self, attrs):
        authenticate_kwargs = {
            self.username_field: attrs[self.username_field],
            'password': attrs['password'],
        }
        try:
            authenticate_kwargs['request'] = self.context['request']
        except KeyError:
            pass

        # print(f"\nthis is the user of authenticate_kwargs {authenticate_kwargs['email']}\n")
       
        
        '''
        Checking if the user exists by getting the email(username field) from authentication_kwargs.
        If the user exists we check if the user account is active.
        If the user account is not active we raise the exception and pass the message. 
        Thus stopping the user from getting authenticated altogether. 
        
        And if the user does not exist at all we raise an exception with a different error message.
        Thus stopping the execution righ there.  
        '''
        try:
         user = CustomUser.objects.get(email=authenticate_kwargs['email'])
         if not user.is_active:
             self.error_messages['no_active_account']=_(
                 'The account is inactive'
             )
             raise exceptions.AuthenticationFailed(
                 self.error_messages['no_active_account'],
                 'no_active_account',
             )
        except CustomUser.DoesNotExist:
          self.error_messages['no_active_account'] =_(
              'Account does not exist')
          raise exceptions.AuthenticationFailed(
              self.error_messages['no_active_account'],
              'no_active_account',
          )
          
        '''
        We come here if everything above goes well.
        Here we authenticate the user.
        The authenticate function return None if the credentials do not match 
        or the user account is inactive. However here we can safely raise the exception
        that the credentials did not match as we do all the checks above this point.
        '''
        
        self.user = authenticate(**authenticate_kwargs)
        if self.user is None:
            self.error_messages['no_active_account'] = _(
                'Credentials did not match')
            raise exceptions.AuthenticationFailed(
                self.error_messages['no_active_account'],
                'no_active_account',
            )
        return super().validate(attrs)

Чтобы настроить эту ошибку, необходимо переопределить сериализатор SimpleJWT. Для этого вам также следует переопределить urls.py и view.py

В представлении вы можете наследоваться от TokenObtainPairView и добавить свой serizlier:

from rest_framework_simplejwt.views import TokenObtainPairView
class YourCustomLoginView(TokenObtainPairView):
    serializer_class = CustomTokenObtainPairSerializer

В сериализаторе необходимо наследоваться от TokenObtainPairSerializer:

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
     ...

Теперь у вас есть 2 варианта отмены сообщения об ошибке (есть и другие альтернативы, но этих двух достаточно):

  1. Вы можете переопределить переменную класса default_error_messages следующим образом:
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer, TokenObtainSerializer):
     default_error_messages = {
        "no_active_account": "your error msg"
    }
  1. Переопределите метод validate, чтобы самостоятельно обрабатывать ошибки валидации:

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from django.contrib.auth import get_user_model, authenticate

class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    _User = get_user_model()

    def validate(self, attrs):
        username_field = self._User.USERNAME_FIELD
        user = self._User.objects.filter(email=attrs[username_field]).first()
        if not user:
            raise AuthenticationFailed({"error": "your error msg"})
        if not user.is_active:                
            raise AuthenticationFailed({"error": "your error msg"})

        authenticate_kwargs = {
            username_field: attrs[username_field],
            "password": attrs["password"],
        }
        user = authenticate(**authenticate_kwargs)
        if not user:
            raise AuthenticationFailed({"error": "your error msg"})
        return super().validate(attrs)

Кроме того, для лучшего понимания рекомендую ознакомиться с сериализаторами TokenObtainPairSerializer и TokenObtainSerializer.

Вернуться на верх