Search code examples
serializationdjango-rest-frameworkdjango-serializer

Got AttributeError when attempting to get a value for field `email` on serializer `LoginSerializer`


Creating a Django API and want to login the user, the login is working but the exceptions not so much. It was working until i wanted to return status

AttributeError at /login/ Got AttributeError when attempting to get a value for field email on serializer LoginSerializer. The serializer field might be named incorrectly and not match any attribute or key on the Response instance. Original exception text was: 'Response' object has no attribute 'email'.

I saw a few answers but the context didnt match. What am i missing or doing wrong?

class LoginSerializer(serializers.ModelSerializer):
    email = serializers.EmailField()
    password = serializers.CharField(max_length=68, min_length=6, write_only = True)
    username = serializers.CharField(
        read_only=True
    )
    tokens = serializers.CharField(max_length=68, min_length=6, read_only=True)
 
    class Meta:
        model=User
        fields = ['email', 'username', 'password', 'tokens']


    def validate(self, attrs):
        email = attrs.get('email', '')
        password = attrs.get('password', '')

        user = auth.authenticate(email=email, password=password)
        if user is None:
            return Response({'msg':'No such user'}, status=status.HTTP_401_UNAUTHORIZED)
            # raise AuthenticationFailed({'status':False,'message': ' username is worng'}, status=status.HTTP_401_UNAUTHORIZED)
        if not user.is_active:
            raise AuthenticationFailed({'msg':'Account is disabled'})
        if not user.is_verified:
            raise AuthenticationFailed({'msg': 'Email is not verified'})
        if not user:
            return Response({'msg':'Invalid credentials, try again'}, status=status.HTTP_401_Unauthorized)

        return{
            'email':user.email,
            'username':user.username,
            'tokens':user.tokens()
        }
        return super.validate(attrs)

'views.py'

class LoginAPIView(APIView):
    serializer_class = LoginSerializer
    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception = True)
        return Response(serializer.data, status=status.HTTP_200_OK)

custom user model

class UserManager(BaseUserManager):
    def create_user(self, username, email, password):
        if username is None:
            raise TypeError("User should be provide username")
        if email is None:
            raise TypeError("User should be provide email")
        if password is None:
            raise TypeError("User should be provide password")

        user = self.model(username=username, email=self.normalize_email(email))
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, username, email, password):
        user = self.create_user(username, email, password)
        user.is_superuser = True
        user.is_staff = True
        user.save()
        return user


class User(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(max_length=255, db_index=True)
    email = models.EmailField(max_length=255, unique=True, db_index=True)
    is_verified = models.BooleanField(default=False)
    # is_authenticated = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']
    objects = UserManager()

    def __str__(self):
        return self.email

    def tokens(self):
        refresh = RefreshToken.for_user(self)
        return {
            'refresh': str(refresh),
            'access': str(refresh.access_token)
        }

Solution

  • def validate(self, attrs):
            email = attrs.get('email')
            password = attrs.get('password')
    
            user = auth.authenticate(email=email, password=password)
            print (user)
            if not user:
                raise AuthenticationFailed({'msg': 'No such user'}, code=status.HTTP_401_UNAUTHORIZED)
            if user is None:
                raise AuthenticationFailed({'message': ' Your Email or Password is wrong'}, code=status.HTTP_401_UNAUTHORIZED)
                # raise AuthenticationFailed({'message': ' username is wrong'})
            if not user.is_active:
                raise AuthenticationFailed({'msg':'Account is disabled'},code=status.HTTP_403_FORBIDDEN)
            if not user.is_verified:
                raise AuthenticationFailed({'msg': 'Email is not verified'}, code=status.HTTP_401_UNAUTHORIZED)
    

    This did the job for me. I guess the error came because the 'auth' did not take 'Response'