본문 바로가기

문돌이 존버/Django 스터디

DRF user 회원가입 UI 아이디, 이메일 중복 검사

반응형

이번엔 서버 측면이 아닌 유저 입장에서 보는 화면 UI 속 아이디 및 이메일 중복 검사를 진행해보겠습니다. 쉽게 말해 저희가 회원가입을 할 때 보통 하는 아이디 중복 검사인 것이죠.  

먼저 아래 serializers.py 에서 validators를 통해 유니크한 아이디를 확인합니다. 

# serializers.py
# 아이디 중복 검사
from rest_framework.validators import UniqueValidator
from .validators import CustomASCIIUsernameValidator # 커스터마이징 버전

class UsernameUniqueCheckSerializer(serializers.ModelSerializer):
    username = serializers.CharField(required=True, min_length=3, max_length=30, validators=[UniqueValidator(queryset=Profile.objects.all()), CustomASCIIUsernameValidator])

    class Meta:
        model = Profile
        fields = ('username')

response를 설정해주는 views.py 는 다음과 같습니다. self.get_serializer(data=request.data) 에 해당하는 부분은 공식 홈페이지를 참고해주세요. get_serializer() 의 파라미터에 대해 설명하고 있습니다.

또한, 저는 CBV(class based view)로 views.py 를 작성하고 아래는 generics의 CreateAPIView를 사용했는데요. 이는 CreateModelMixin 클래스를 상속한 것으로 CreateModelMixin 원본 코드는 여기를 참고해주세요. 해당 코드에서 def create() 부분을 살펴보면 아래 형식이 잘 이해가 될 겁니다. 

Generics views를 더 이해하고 싶다면 공식 홈페이지를 참고해주세요. 반복적이고 귀찮은 CRUD를 간편하게 사용 가능하고, 오버라이딩도 할 수 있는 방식입니다. url를 연결할 때도 .as_view() 방식을 통해 관련 CRUD를 적용할 수 있습니다. 

# views.py
from rest_framework.response import Response
from rest_framework import generics
from rest_framework import status

from .serializers import UsernameUniqueCheckSerializer

class UsernameUniqueCheck(generics.CreateAPIView):
    serializer_class = UsernameOverlapSerializer

    def post(self, request, format=None):
        serializer = self.get_serializer(data=request.data, context={'request': request})
        if serializer.is_valid():
            return Response(data={'detail':['You can use this ID']}, status=status.HTTP_200_OK)
        else:
            detail = dict()
            detail['detail'] = serializer.errors['username']
            return Response(data=detail, status=status.HTTP_400_BAD_REQUEST)
# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('uniquecheck/username', views.UsernameUniqueCheck.as_view(), name='uniquecheck_username'),
]

아래는 공식 홈페이지에 소개된 context 사용 예시입니다. 시리얼라이즈되는 객체 정보 이외의 context를 받고 싶을 경우 사용합니다. 흔하게 출력하는 것은 request를 받은 해당 API의 url입니다. 

제가 코드 중간에 print(serializer)를 해본 결과 아래의 출력 결과를 얻었습니다. context에 해당하는 딕셔너리를 살펴보시면 총 3가지 key가 있음을 확인할 수 있습니다.

1. request
2. format
3. view
UsernameUniqueCheckSerializer(context={'request': <rest_framework.request.Request: POST '/****/****/****'>, 'format': None, 'view': <accounts.views.UsernameUniqueCheck object>}, data=<QueryDict: {'csrfmiddlewaretoken': ['*******************'], 'username': ['tester']}>)

공식 홈페이지에 소개된 serializer.erros 를 보면 잘못 입력한 것에 대해 아래와 같이 딕셔너리 형태로 리턴하게 됩니다.

제가 작성한 코드 예시로는 아이디가 중복될 경우 아래와 같은 에러 메시지가 뜨네요. 

반대로 유저가 사용하고자 하는 아이디가 유니크하다면 아래와 같은 메시지를 얻게 됩니다.

이메일 및 닉네임 중복 검사도 위와 동일하게 진행하면 되겠습니다. 

# serializers.py
# 이메일 중복 검사
class EmailUniqueCheckSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(required=True, validators=[UniqueValidator(queryset=Profile.objects.all())])

    class Meta:
        model = Profile
        fields = ('email')
        
 # 닉네임 중복 검사
class NicknameUniqueCheckSerializer(serializers.ModelSerializer):
    nickname = serializers.CharField(required=True, min_length=1, max_length=30, validators=[UniqueValidator(queryset=Profile.objects.all())])

    class Meta:
        model = Profile
        fields = ('nickname')
# views.py
class EmailUniqueCheck(generics.CreateAPIView):
    serializer_class = EmailUniqueCheckSerializer

    def post(self, request, format=None):
        serializer = self.get_serializer(data=request.data, context={'request': request})

        if serializer.is_valid():
            return Response(data={'detail':['You can use this email']}, status=status.HTTP_200_OK)
        else:
            detail = dict()
            detail['detail'] = serializer.errors['email']
            return Response(data=detail, status=status.HTTP_400_BAD_REQUEST)
            
 class NicknameUniqueCheck(generics.CreateAPIView):
    serializer_class = NicknameUniqueCheckSerializer

    def post(self, request, format=None):
        serializer = self.get_serializer(data=request.data, context={'request': request})
        if serializer.is_valid():
            return Response(data={'detail':['You can use this nickname']}, status=status.HTTP_200_OK)
        else:
            detail = dict()
            detail['detail'] = serializer.errors['nickname']
            return Response(data=detail, status=status.HTTP_400_BAD_REQUEST)
# urls.py
urlpatterns = [
    path('uniquecheck/email', views.EmailUniqueCheck.as_view(), name='uniquecheck_email'),
    path('uniquecheck/nickname', views.NicknameUniqueCheck.as_view(), name='uniquecheck_nickname'),
]

자, 이로써 유저 계정 관련 굵직한 작업은 마무리한 것 같습니다. 다음에는 게시글 및 댓글 작성을 살펴보겠습니다.

728x90
반응형