Notice
Recent Posts
Recent Comments
Link
오늘도 개발
[2차 프로젝트 내일의 집] get_or_create 사용하기 본문
구현하고 싶은 것
유저의 kakao 아이디가 DB에 저장되어 있는 경우 => 추가 작업 없이 토큰 발행
유저의 kakao 아이디가 DB에 없는 경우 => DB에 새 유저 row 생성, 토큰 발행
처음 생각한 코드
exists()로 유저 아이디가 DB에 있는지 확인하고
있으면 토큰 발급,
없으면 User.objects.create을 실행한다.
if User.objects.filter(kakao_id = kakao_id).exists():
nhouse_token = jwt.encode({"user_id" : user.id}, settings.SECRET_KEY, settings.ALGORITHM)
return JsonResponse({"message" : "LOGIN_SUCCESS", "access_token" : nhouse_token}, status=200)
else:
User.objects.create(
kakao_id = kakao_id,
email = email,
nickname = nickname,
profile_image = profile_image
)
nhouse_token = jwt.encode({"user_id" : user.id}, settings.SECRET_KEY, settings.ALGORITHM)
return JsonResponse({"message" : "SIGNUP_SUCCESS", "access_token" : nhouse_token}, status=201)
get_or_create
원래 get_or_create는 race condition을 방지할 목적으로 나왔지만
여기에서는 코드를 간결하게 작성하기 위한 목적으로 사용할 수 있다.
get_or_create는 get을 실행한 뒤 튜플(오브젝트, True/False)을 반환한다.
get의 결과가 있으면 get의 결과를 오브젝트에 넣고, False를 반환한다.
get의 결과가 없으면 새로 생성해서 오브젝트에 넣고, True를 반환한다.
튜플의 두번째 값이 True인 경우에만 오브젝트에 값을 넣어 DB에 저장한다.
user, is_created = User.objects.get_or_create(kakao_id = kakao_id)
nhouse_token = jwt.encode({"user_id" : user.id}, settings.SECRET_KEY, settings.ALGORITHM)
if is_created:
user.email = email
user.nickname = nickname
user.profile_image = profile_image
user.save()
return JsonResponse({"message" : "SIGNUP_SUCCESS", "access_token" : nhouse_token}, status=201)
else:
return JsonResponse({"message" : "LOGIN_SUCCESS", "access_token" : nhouse_token}, status=200)
리팩토링
하지만 위와 같은 방법으로 진행했을 때
- 이미 존재하는 유저의 정보를 가져오거나
- 없는 유저를 새로 저장하기만 가능하다.
이미 존재하는 유저의 nickname이 바뀐 경우 DB에 저장할 수 없다.
위 코드를 리팩토링해서 등록된 유저 정보가 바뀐 경우에 업데이트할 수 있게 만들었다.
또 defaults를 사용하면 더 가독성 있는 코드로 바꾸어보았다.
user, is_created = User.objects.get_or_create(
# 장고는 defaults 바깥에 있는 항목을 사용하여 DB에 존재하는 오브젝트인지 확인한다.
# 즉 아래 코드는 동일한 kakao_id와 email이 DB에 있는지 확인하고 get이나 create를 실행한다.
kakao_id = kakao_id,
email = email,
defaults = {
# DB에 없는 유저인 경우 defaults에 입력한 값으로 새 유저를 생성하고 DB에 저장한다.
"nickname" : nickname,
'profile_image' : profile_image
}
)
nhouse_token = jwt.encode({"user_id" : user.id}, settings.SECRET_KEY, settings.ALGORITHM)
# DB에 존재하는 유저인 경우
if not is_created:
# 프로필 이미지가 바뀌었으면 업데이트해서 저장한다.
if not user.profile_image == profile_image:
user.profile_image = profile_image
user.save()
# 닉네임이 바뀌었으면 업데이트해서 저장한다.
if not user.nickname == nickname:
user.nickname = nickname
user.save()
return JsonResponse({"message" : "LOGIN_SUCCESS", "access_token" : nhouse_token}, status=200)
return JsonResponse({"message" : "SIGNUP_SUCCESS", "access_token" : nhouse_token}, status=201)
'TIL & 프로젝트 회고' 카테고리의 다른 글
| [2차 프로젝트 내일의 집] 포스트 목록 api - Django ORM 최적화하기 (0) | 2022.08.07 |
|---|---|
| [2차 프로젝트 내일의 집] SNS 로그인/회원가입 api에 Unit Test 해보기 (0) | 2022.08.05 |
| [2차 프로젝트 내일의 집] 카카오 api로 SNS 로그인/회원가입 구현하기 (0) | 2022.08.03 |
| [1차 프로젝트 록차] 프로젝트 최종 회고 (0) | 2022.07.29 |
| [1차 프로젝트 록차] API 명세서 작성해보기 (0) | 2022.07.27 |