코드로 우주평화
[TIL]django__데이터 중복_IntegrityError_ValidationError 본문
오늘 배운 것
회원가입 시 이메일 정보가 중복되면 에러로 반환하고 싶다.
장고 view에서 데이터의 중복을 확인하는 방법에는 여러 가지가 있는데 한 번 살펴보자.
처음에 나는 회원정보가 있는 Member테이블에서 email 칼럼의 값을 리스트 형태로 가져와 변수에 저장했다.
그리고 요청받은 email 데이터가 해당 리스트에 있는지 확인 하는 식으로 코드를 작성했다. 코드는 다음과 같다.
email_list = Member.objects.values_list("email", flat=True)
if data['email'] in email_list: # data['email']은 요청받은 이메일 정보이다.
return ~~
그리고 동료로부터 배운 두 번째 방법은 exists()매서드를 활용에 중복 여부를 확인하는 방법이다.
이렇게 하면 굳이 이메일 데이터의 리스트를 만들 필요가 없어진다. 메서드를 활용해 1개 이상 존재하는지 여부를 판단할 수 있기 때문이다.
if Member.objects.filter(email=data["email"]).exists():
return ~~
마지막 세 번째 방법은 models.py에 해당 필드안에 unique=True속성을 부여하는 것이다. 이 속성을 부여하면 1개 이상의 동일한 데이터가 들어올 경우 자동으로 에러 메시지를 반환해 준다. 우리는 이 에러 메시지를 핸들링하여 우리가 원하는 형태로 다시 반환하면 된다.
이를 위해서는 먼저 뷰파일에 IntegrityError를 임포트 한 후, try:~except:을 이용하여 오류를 핸들링할 수 있다.
from django.db.utils import IntegrityError
try:
~~
except IntegrityError:
return ~~
하지만 문제가 발생했다.
내 코드에서 이를 실행하면 정상적으로 작동은 하지만 데이터베이스 테이블에는 pk가 하나씩 증가하는 문제가 생겼다. (사진 첨부)
아직까지 이 문제는 해결하지 못했다...
테이블에 pk가 늘어나는 것은 장기적으로 볼 때 오류가 생길 위험이 있으므로 해당 코드는 쓰지 않기로 결정했다.
이를 해결하기 위해 또다시 동료의 조언을 듣고 에러 핸들링을 수정하였다. (아래 코드 참고)
from django.core.exceptions import ValidationError
class SignupView(View):
def post(self, request):
try:
data = json.loads(request.body)
email = data["email"]
password = data["password"]
if not re.match(email_regexp, email):
return JsonResponse({'massage':"EMAIL_ERROR"}, status=400)
elif not re.match(password_regexp , password):
return JsonResponse({'massage':"PASSWORD_ERROR"}, status=400)
else :
member = Member(
name = data["name"],
email = email,
password = password,
phone_number = data["phone_number"],
information = data["information"]
)
member.full_clean()
member.save()
return JsonResponse({'massage':"SUCCESS"}, status=201)
except ValidationError as e:
return JsonResponse({'massage':"VALIDATION_ERROR"+" "+str(e)}, status=400)
except KeyError as e:
return JsonResponse({'massage':"KEY_ERROR"+" Missing"+str(e)}, status=400)
기존에는 한번에 create 하여 테이블에 데이터를 넣어주었는데, 이번에는 데이터를 member라는 변수에 넣고 full_clean()을 통해 유효성 검사를 수행하도록 수정했다. 참고 링크
full_clean()을 이용하면 모델에서 지정한 속성에 적합하지 않은 경우, ValidationError를 반환한다. 이를 이용해 에러를 핸들링하니 테이블의 pk가 증가하지 않았고 정상적으로 데이터가 입력되는 것을 확인할 수 있었다.
오늘 느낀 것
- 배운 만큼 보인다고 동료가 조언을 해주지 않았다면 무식하게 리스트를 활용하여 중복검사를 진행했을 것이다. 이를 해결하기 위해서는 동료들과 코드를 주기적으로 공유하고, 뿐만 아니라 공식문서나 다른 사람들의 코드를 찾아보면서 시야를 넓혀야겠다는 생각이 들었다.
- 코딩에 정답이 없음을 느꼈다. 한 가지 답을 찾았다고 거기에 멈추지 말고 다양한 경우와 다양한 코드를 다시 적용해보는 연습을 하면 좋겠다는 생각이 든다. 특히 알고리즘을 풀면서 다양한 시도를 해보는 게 중요하겠다는 생각이 들었다.
- 위에서 언급한 pk가 증가하는 문제는 아직 원인도 정확히 파악하지 못했다. 다만 추측하기로는 데이터 생성이 먼저 이루어지고 이메일 중복을 거친 후 유효하지 않으면 데이터가 다시 지워지기 때문에 발생한 문제가 아닐까 싶다. 이 부분에 대해서는 멘토님께 문의를 했는데 답을 받는다면 추가로 글에 기재하겠다.
'나는 이렇게 학습한다 > Debug' 카테고리의 다른 글
SQLAlchemy _ NotSupportedError(InvalidCachedStatementError) 에러 해결 (0) | 2022.04.29 |
---|---|
컬럼 속성 변경 후 alembic migration할 때 ‘None’ 생기는 현상 (0) | 2022.04.26 |
pytest _ 하나의 함수에서 복수 케이스 테스트 하는 방법 (0) | 2022.04.20 |
@pytest.fixture 로 test 데이터 세팅하기 (0) | 2022.04.14 |
내가 쓴 Python 테스트 코드 coverage 알아보기 (0) | 2022.03.20 |