코딩 개발일지

DRF 로그인 / 회원탈퇴 본문

AI 본 교육/AI 13주차

DRF 로그인 / 회원탈퇴

호기호 2023. 11. 7. 15:54

로그인

<views.py>

class LoginView(TokenObtainPairView):
    serializer_class = LoginSerializer

 

<serializers.py>

class LoginSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token['email'] = user.email
        token['nickname'] = user.nickname
        token['profile_img'] = user.profile_img.url

        return token

 

이젠 익숙한 login 기능.

근데, error 메세지가 맘에 안들어서 직접 custom하기로 했음.

TokenObtainPairSerializer, TokenObtainSerializer 를 [ctrl+클릭] 해서 django 기본 제공 코드를 참고해서 custom 해줌.

 

<변경 후 serializers.py>

class LoginSerializer(TokenObtainPairSerializer):
   
    email = serializers.EmailField(required=True)
    password = serializers.CharField(required=True, write_only=True)

    def validate(self, request_data):
        request_email = request_data.get('email')
        request_password = request_data.get('password')

        try:
            user = User.objects.get(email=request_email)
        except User.DoesNotExist:
            raise exceptions.NotFound({'status':'404', 'error':'사용자를 찾을 수 없습니다. 로그인 정보를 확인하세요.'})
       
        if not user.check_password(request_password):
            raise exceptions.AuthenticationFailed({'status':'401', 'error':'비밀번호가 일치하지 않습니다.'})
        else:
            data = super().validate(request_data)
            return data

    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token['email'] = user.email
        token['nickname'] = user.nickname
        token['profile_img'] = user.profile_img.url

        return token

 

추후에 이메일 인증 기능을 추가하면, is_active=False 일 때, 이메일인증을 해달라는 error 매세지도 custom 해줄 것이다!!


회원 탈퇴

회원탈퇴는 serializer를 쓸 수도 있겠지만, 그냥 user를 delete 해주면 끝나는 작업이기때문에, 그냥 views.py에서 끝냈다.

 

<views.py>

class UserInfoView(APIView):
    permission_classes = [permissions.IsAuthenticated]
 
    def delete(self, request):
        if request.data:
            password = request.data.get("password", "")
            auth_user = authenticate(email=request.user.email, password=password)
            if auth_user:
                auth_user.delete()
                return Response({'status': '204', 'error': '회원 탈퇴가 완료되었습니다.'}, status=status.204ㄱㄱ)
            else:
                return Response({'status': '401', 'error': '비밀번호가 불일치합니다.'}, status=status.401ㄱㄱ)
        else:
            return Response({'status': '400', 'error': '비밀번호를 입력해주세요.'}, status=status.HTTP_400_BAD_REQUEST)

(칸 넘어가서 204ㄱㄱ / 401ㄱㄱ 로 바꾼거 안비밀)

원랜 email도 입력 받게 만들었는데, 생각해보니 password만 받으면 될 것 같아서 바꿨당.

 

auth_user = authenticate(email=request.user.email, password=password)
django의 authenticate 함수를 사용하여 사용자를 인증한다. user의 password를 기반으로 사용자를 찾고, 올바른 인증 정보인 경우 사용자 객체를 반환한다. 만약 올바른 정보가 아니면 auth_user는 None이 된다.

 

password = request.data.get("password", "")
이 코드는 "password" 키가 request.data에 존재하지 않거나 값이 없을 때 기본값으로 빈 문자열("")을 할당합니다. 이렇게 하면 "password" 키가 없어도 예외가 발생하지 않으며, 코드는 계속 진행됩니다. 이것은 안전한 방식으로, 사용자가 비밀번호를 제공하지 않았을 때 예외를 방지하고 빈 문자열을 사용하여 나중에 인증을 처리할 때 비밀번호의 빈 값 여부를 확인할 수 있습니다.
password = request.data.get("password")
이 코드는 "password" 키가 request.data에 존재하지 않을 경우 None을 반환합니다. 따라서 만약 "password" 키가 없는 경우에는 None을 password 변수에 할당하게 되고, 이후 코드에서 password 변수를 사용할 때 None을 처리해야 합니다. 만약 처리하지 않으면 NoneType 객체에서 비밀번호를 가져오려 할 때 AttributeError 예외가 발생할 수 있습니다.


따라서 password = request.data.get("password", "") 를 사용하는 것은 안전한 프로그래밍 방식이며, 예외를 방지하고 비밀번호가 제공되지 않은 경우 빈 문자열로 초기화하여 나중에 처리하기 편리합니다.


이번 프로젝트는 공을 정말 많이들여서 에러메세지도 하나하나 custom해줄 예정이다.

직접 custom하는 이유중 하나는 frontend와 연동시킬 때, error status랑 message를 str로 보내주면 좋다는 말을 듣고, 이렇게 코드를 완성했다.