될때까지

((WnB)) 6일차 : 사용자 추가 정보 입력받기 본문

프로젝트/wecode2차 : WnB

((WnB)) 6일차 : 사용자 추가 정보 입력받기

랖니 2022. 8. 6. 19:56
728x90

카카오 프로필 이미지와 WnB 프로필 이미지 동기화

유저가 카카오톡에서 프로필 이미지를 변경한 경우, DB에 저장된 프로필 이미지와 달라진다. 똑같이 유지할 순 없을까 생각하다가 if문을 추가해서 카카오톡 상의 프로필 이미지와 wnb의 이미지를 똑같게 변경하는 코드를 추가했다. if와 똑같은 코드의 반복이 마음에 안들지만.. 지금 생각해낼 수 있는 코드는 저게 전부...!

class KakaoOauthView(View):
    def get(self, request):
        token = request.META.get('HTTP_AUTHORIZATION')

        KAKAO_URL = 'https://kapi.kakao.com/v2/user/me'
        HEADER    = {'Authorization': token}
        
        user_info = requests.get(KAKAO_URL,headers=HEADER).json()
        
        kakao_id          = user_info['id']
        kakao_profile_img = user_info['kakao_account']['profile']['profile_image_url']
        email             = user_info['kakao_account']['email']
        
        user, created = User.objects.get_or_create(
            kakao_id = kakao_id
        ) 
        
        if created:
            user.kakao_profile_img = kakao_profile_img
            user.email             = email
            user.save()
            
            return JsonResponse({'message':'SIGNUP_SUCCESS'}, status=201)
        
        else:
            if user.kakao_profile_img != kakao_profile_img:
                user.kakao_profile_img = kakao_profile_img
                user.save()
            
            token = jwt.encode({'id':user.id}, settings.SECRET_KEY, settings.ALGORITHM)
            
            return JsonResponse({'message':'SIGNIN_SUCCESS', 'token':token}, status=200)

 

회원가입에 필요한 유저 추가 정보 저장하는 기능

class UserUpdateView(View):
    @signin_decorator
    def patch(self, request):
        """
        클라이언트로 부터 입력되는 값들
        first_name   => 한글만 
        last_name    => 한글만
        phone_number => '???-????-????'
        
        등록하면 안되는 경우가 있을까? => 이미 앞에서 회원가입/로그인 여부를 반환했고 데코레이터를 사용한다.
        그럼 연락처만 중복인지 확인하는 로직을 추가해서 사용자 정보 업데이트 기능을 작성하자.
        
        1. 키값자체가 입력이 안된 경우?
        2. 정규표현식에 맞지 않는 경우?
        3. 이미 중복된 핸드폰인 경우
        
        """
        try: 
            user = request.user
            data = json.loads(request.body)   # patch는 body에 데이터가 담겨서 온다.
        
            first_name   = data['first_name']
            last_name    = data['last_name']
            phone_number = data['phone_number']
            birth_day    = data['birth_day']
                      
            # 유효성 검사
            check_first_name(first_name)
            check_last_name(last_name)
            check_phone_number(phone_number)
            
            # 연락처가 중복인 경우
            if User.objects.filter(phone_number = phone_number):
                return JsonResponse({'message':'PHONE_NUMBER_ALREADY_EXIST'}, status=401)
            
            # 입력받은 사용자 정보를 DB에 저장
            user.first_name   = first_name
            user.last_name    = last_name
            user.phone_number = phone_number
            user.birth_day    = birth_day
            user.save()

            return JsonResponse({'message':'USER_INFO_UPDATED'}, status=201)
            
        except KeyError:
            return JsonResponse({'message':'KEY_ERROR'}, status=400)
        
        except ValidationError as e:
            return JsonResponse({'message':f'{e}'}, status=400)

- 로그인 데코레이터를 사용하기 때문에 user에 대한 확인을 할 필요가 없다.

- 생년월일은 프론트에서 달력으로 표현했고 선택한 날짜에 대해 '????-??-??'으로 들어오기 때문에 확인식을 작성하지 않았다.

- 핸드폰번호는 중복인 경우 업데이트 못되게 작성했다.

- url을 /users/additional-info로 만들었는데, '/users/<int:user_id>/info' 처럼 path parameter를 사용할 수도 있지 않을까?

 

 

뻘짓

1시간 40분을 괴롭히던 에러.. ^^ 

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

나의 경우 원인은 포스트맨에 있었다.

content-type과 content-length를 체크안했었......다........... 미안해요 도연님 ^___^ 

 

굳이?

def signin_decorator(func):
    def wrapper(self, request, *args, **kwargs):
        try:
            # if 'Authorization' not in request.headers:
            #     return JsonResponse({'message':'KEY_ERROR'}, status=400)
            
            token        = request.headers.get('Authorization')   # 여기서 이미 에러가 발생하면
            payload      = jwt.decode(token, settings.SECRET_KEY, settings.ALGORITHM)
            user         = User.objects.get(id = payload['id'])
            request.user = user
            
            return func(self, request, *args, **kwargs)
            
        except User.DoesNotExist:
            return JsonResponse({'message':'INVALID_USER'}, status=400)
        
        except jwt.exceptions.DecodeError:   # 여기로 빠진다.
            return JsonResponse({'message':'INVALID_TOKEN'}, status=400)
    return wrapper

if문으로 처리한 에러는 애초에 해당 벨류값이 없는 경우 except에서 처리한 jwt.DecodeError로 빠지게 된다. 굳이 분기처리하지않아도 에러를 반환하게 되니까 빼도 무방하다!

 

정규표현식

def check_first_name(value):
    if not re.match('^[ㄱ-ㅎ|가-힣]+$', value):
        raise ValidationError("FISRT_NAME_ERROR")
    
def check_last_name(value):
    if not re.match('^[ㄱ-ㅎ|가-힣]+$', value):
        raise ValidationError("LAST_NAME_ERROR")
    
def check_phone_number(value):
    if not re.match('^01([0|1|6|7|8|9])-([0-9]{3,4})-([0-9]{4})$', value):
        raise ValidationError("PHONE_NUMBER_ERROR")

성과 이름은 한글만 가능하고, 연락처는 010-1111-1111과 같은 형식으로만 받을 수 있다.

 

728x90