models.py 에서 Field 값에 Null=True 를 지정해 준 경우, create를 할 때 python get() 함수를 이용해서 아래와 같이 default 값을 None 값으로 지정해준다.
User.objects.create(
information = data.get("info"),
)
만약 Field 값을 blank=True로 지정해주었을 경우, 아래와 같이 default값을 빈 문자열로 지정해준다.
User.objects.create(
information = data.get("info", ""),
)
[Object.DoesNotExist를 사용한 경우]
[Model.DoesNotExist를 사용한 경우]
Django에서는 Object.DoesNotExist보다 Model.DoesNotExist 사용을 선호한다.
Model.DoesNotExist를 사용할 경우 위의 예시와 같이 특정한 모델이 존재하지 않을 때에만 예외로 처리할 수가 있어서 더 세세하게 에러 관리를 할 수가 있고 더 효율적이다. 또한, ObjectDoesNotExist가 import 되어있는지를 따로 확인할 필요없이 내장되어있는 .DoesNotExist를 이용한다는 점에서 편리하다.
model.py에서 email Field에 unique=True 값을 주어 중복 가입이 되지 않도록 설정했고, 회원가입 시 이미 존재하는 이메일인지를 검증하는 과정에서 이미 존재하는 이메일일 경우를 IntegrityError로 예외처리를 했었다.
그런데 데이터가 DB에 저장될 때, 회원가입 실패 시도 횟수만큼 id 값이 밀려서 DB에 저장되는 것을 확인했고, 이 에러를 적용할 경우 DB를 한번 hit하고 나온다는 것을 알게되었다.
정확한 이유는 알 수 없지만 아마도 create과정에서 name값이 email값보다 먼저 생성되기 때문에, DB에 name을 생성하고 나서 email을 생성하는 과정에서 이메일의 중복을 확인하게 되고, 이후 DB에서 저장되지 않고 에러처리가 되어서 DB에서 id값이 생성되었다가 사라지는 것이 원인이라고 추측해볼 수 있다.
[id값이 밀려서 저장되는 예시]
-> 12번으로 저장된 후 5번의 실패 시도 이후 저장된 값은 18번이었음
처음에는 get을 사용해서
User.objects.get(email=data['email']).password
로 가져온 값이 data['password'] 와 같지 않으면 에러들을 exception으로 발생시키는 로직을 사용했는데,
멘토님들께 리뷰를 받은 후 filter로 email과 password값을 받아서 일치하는 값이 존재하지 않으면 INVALID_USER 로 리턴하고 KeyError만 예외처리하는 로직으로 변경하여
아래와 같이 코드를 효율적으로 줄일 수 있게 되었다.
이후, bcrypt로 비밀번호를 암호화하는 과정에서 쿼리셋이 아닌 값을 받아와야하기 때문에 filter로 값을 받아오는 과정을 get으로 다시 변경해서 아래와 같이 다시 코드가 수정되었다.
References
Django Exception :
https://docs.djangoproject.com/en/3.2/ref/exceptions/