[ PROJECT ] Westgram endpoint 구현 (4) - 마무리 리뷰!
0. 변수명은 간단하게!
class User(models.Model):
user_name = models.CharField(max_length=30, unique=True)
-> 이렇게 해주면 무조건 unique하게 입력되기 때문에
추후에 회원가입 시 무조건 unique하게 입력되고,
로그인 시에도 filter(), get()메서드를 사용했을 때 unique한 값만 가져올 수 있다.
class User(models.Model):
user_name = models.CharField(max_length=30, unique=True)
-> 이렇게 해주면 무조건 unique하게 입력되기 때문에
추후에 회원가입 시 무조건 unique하게 입력되고,
로그인 시에도 filter(), get()메서드를 사용했을 때 unique한 값만 가져올 수 있다.
👆🏻 models.py에서 테이블을 정의할 때, 불필요하게 변수명을 길게 작성한 나..!
user = User.objects.get(id=1)
user.name
👆🏻 추후에 views.py에서 로직을 작성할 때, model 내 각 클래스에서 해당 필드의 값을 가져올 때, 불필요하게 user.user_name
이라고 쓰는 것보다는 user.name
이렇게 적는 것이 더 가독성이 좋다!
🤩 수정한 모습
from django.db import models
class User(models.Model):
name = models.CharField(max_length=30, unique=True, default='')
password = models.CharField(max_length=100)
class Meta:
db_table = 'users'
1. json decode 에러 방지하기
def post(self, request):
data = json.loads(request.body)
try:
.....
def post(self, request):
data = json.loads(request.body)
try:
.....
이런 식으로 작성을 하면, 만에하나 프론트엔드에서 보내준 데이터가 없어서 json이 load할 데이터가 없다면
raise Exceptions ......
👆🏻요로케 decode
에러가 raise된다.
def post(self, request):
try:
data = json.loads(request.body)
.....
except JsonDecodeError:
.....
이런식으로 만에하나 에러날 수도 있는 상황을 try문 안에 넣어주고,
구체적으로 except 상황을 명시해 줄 것 (물론 decode에러
외에 다른 에러들도 명시해줘야 한다..!)
🤩 수정한 모습
import json
import re
import bcrypt
import jwt
from django.http import JsonResponse
from django.views import View
from user.models import User
from westagram.settings import SECRET_KEY, ALGORITHM
# sign up
class Signup(View):
def post(self, request):
try:
data = json.loads(request.body)
if data.get('name') is not None:
if data.get('password') is not None:
if User.objects.filter(name=data['name']).count() > 0:
return JsonResponse({'message':'DUPLICATED_USERNAME'}, status=400)
if re.search('[0-9]+', data['password']) is None:
return JsonResponse({'message':'TOO_SHORT_PW'}, status=400)
hashed_password = bcrypt.hashpw(data['password'].encode('utf-8'), bcrypt.gensalt())
User.objects.create(
name = data['name'],
password = hashed_password.decode('utf-8')
)
return JsonResponse({'message':'SUCCESS'}, status=200)
except KeyError: <- 요 구간!
return JsonResponse({'message':'KEY_ERROR'}, status=400)
except ValueError:
return JsonResponse({'message':'DECODE_ERROR'}, status=400)
2. 간결한 if문
def post(self, request):
try:
data = json.loads(request.body)
if data.get('user_name') is not None:
def post(self, request):
try:
data = json.loads(request.body)
if data.get('user_name') is not None:
이렇게 구구절절 써둔 나의 if문...
하지만 json형식으로 들어온 data 변수는 이미 dictionary
형식이므로
.get()
메서드 사용 시 값이 없으면 무조건 None을 반환하기 때문에
굳이 if문을 저렇게 길게 작성할 필요가 없다!
그리고 data에서 가져온 값들을 따로 변수에 담아두지 않으면
계속해서 다시 상단으로 돌아가서 data 변수 내의 값들을 확인하기 때문에,
자주 쓰이는 값들은 변수에 담아서 준비해 두는 것이 좋다! (가독성 측면에서도..!)
name = data.get('name')
password = data.get('password')
if name or password 👍 :
return ...
👆🏻 요로케만 작성해주어도 되는 것!!!
3. filter()로 DB 내 데이터 존재여부 확인하기
if name:
if User.objects.filter(name=name).exists():
return ...
if len(password) < 5:
return ...
if name:
if User.objects.filter(name=name).exists():
return ...
if len(password) < 5:
return ...
이미 filter()
라는 메서드는 해당하는 값을 하나만 가져오기 때문에 굳이 내가 했었던 것 처럼 .count()
메서드로 개수를 세어줄 필요가 없다..!
그저 가져온 값이 존재하는지, 존재하지 않는지만 보면 되는 것..!
🤩 수정한 모습
class Signup(View):
def post(self, request):
try:
data = json.loads(request.body)
name = data.get('name')
password = data.get('password')
if name:
if password:
if User.objects.filter(name=name).exists():
return JsonResponse({'message':'DUPLICATED_USERNAME'}, status=400)
if len(password) < 8:
return JsonResponse({'message':'TOO_SHORT_PW'}, status=400)
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
User.objects.create(
name = name,
password = hashed_password.decode('utf-8')
)
return JsonResponse({'message':'SUCCESS'}, status=200)
except KeyError:
return JsonResponse({'message':'KEY_ERROR'}, status=400)
except ValueError:
return JsonResponse({'message':'DECODE_ERROR'}, status=400)
4. 상황에 맞는 status 코드!
status
code!
- 200
: data get
, post
, update
처리를 성공하였을 때
- 201
: 데이터resource
가 생성된 경우
- 400
: front-end
의 요청에 대한 처리 불가할 때
: bad request
- 401
: 권한이 요구되지 않았을 때
5. 지저분한 except 처리
else:
return JsonResponse({'message':'KEY_ERROR'}, status=400)
else:
return JsonResponse({'message':'KEY_ERROR'}, status=400)
except:
return JsonResponse({'message':'KEY_ERROR'}, status=400)
status
code!
- 200
: dataget
,post
,update
처리를 성공하였을 때 - 201
: 데이터resource
가 생성된 경우 - 400
:front-end
의 요청에 대한 처리 불가할 때
:bad request
- 401
: 권한이 요구되지 않았을 때
else:
return JsonResponse({'message':'KEY_ERROR'}, status=400)
else:
return JsonResponse({'message':'KEY_ERROR'}, status=400)
except:
return JsonResponse({'message':'KEY_ERROR'}, status=400)
모든 if문에 대한 예외처리를 각각의 except로 통일한 내 코드!
아무리 생각해도 이것보다 깔끔하게 처리를 할 수 있을 것 같은데... 궁금하던 찰나!
except KeyError:
return JsonResponse()
except User.DoesNotExist:
return JsonReponse()
except User.MutipleObjectReturn:
return JsonResponse({'message' :'DUPLICATE_USER'}, status=409)
👆🏻 어짜피 저 모든 상황에서 날 예외는 key error
이기때문에, except
에 구체적으로 어떤 에러에 대한 상황인지 명시해주면
하나의 except
여도 잘 처리할 수 있다!
최종 views.py 로직(회원가입, 로그인)
🤯 🥺 🤩
import json
import re
import bcrypt
import jwt
from django.http import JsonResponse
from django.views import View
from user.models import User
from westagram.settings import SECRET_KEY, ALGORITHM
# sign up
class Signup(View):
def post(self, request):
try:
data = json.loads(request.body)
name = data.get('name')
password = data.get('password')
if name:
if password:
if User.objects.filter(name=name).exists():
return JsonResponse({'message':'DUPLICATED_USERNAME'}, status=400)
if len(password) < 8:
return JsonResponse({'message':'TOO_SHORT_PW'}, status=400)
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
User.objects.create(
name = name,
password = hashed_password.decode('utf-8')
)
return JsonResponse({'message':'SUCCESS'}, status=200)
except KeyError:
return JsonResponse({'message':'KEY_ERROR'}, status=400)
except ValueError:
return JsonResponse({'message':'DECODE_ERROR'}, status=400)
# sign in
class Signin(View):
def post(self, request):
try:
data = json.loads(request.body)
name = data['name']
password = data['password']
user_info = User.objects.get(name=name)
signin_id = user_info.name
signin_pw = user_info.password.encode('utf-8')
if User.objects.filter(name=name).exists():
if signin_id == name and bcrypt.checkpw(password.encode('utf-8'), signin_pw):
access_token = jwt.encode({'name':name}, SECRET_KEY, algorithm = ALGORITHM).decode('utf-8')
return JsonResponse({'message':'SUCCESS', 'access_token':access_token}, status=200)
except KeyError:
return JsonResponse({'message':'KEY_ERROR'}, status=401)
except ValueError:
return JsonResponse({'message':'INVALID_USER'}, status=401)
except User.MultipleObjectsReturned:
return JsonResponse({'message':'MULTIPLE_USERS'}, status=409)
사실 따지고보면django.core.exceptions
의 MultipleObjectsReturned
는 사용하지 않았으니까 제거하는게 맞았는데..
저 exception
을 사용하려고 해봤더니 자꾸 model에서 에러가 난다고 하는 것이 아닌가..!
공식 문서를 확인한 결과, model class
에서 사용하는 것이라고 한다. 👉🏻 Model Class Reference
(model class
에 import 하고 views.py에서 exception MultipleObjectsReturned
로 쓰는 것이었음!)
오늘의 평화로운 코딩 끗!
(현재시각 새벽 4:35분 휴..)
Author And Source
이 문제에 관하여([ PROJECT ] Westgram endpoint 구현 (4) - 마무리 리뷰!), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@haileeyu21/PROJECT-Westgram-endpoint-구현-4-마무리-리뷰저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)