처음 DRF를 배울 때, 프로젝트를 시작하고 처음 기능 구현을 시작하는 것은 보통 회원가입 기능이었습니다. 이 때, 처음 접하는 클래스 뷰(CBV, Class Based View)와 시리얼라이저도 낯설었지만 그 정도는 일단 먼저 구현해보고 분석해도 충분하다고 생각했습니다. 하지만 회원가입부터 도저히 이해가 안가는 부분이 있었어서 그 부분에 대해서 정리해보려고 합니다.
1 class RegisterView(APIView):
2 def post(self, request):
3 """사용자 정보를 받아 회원가입 합니다."""
4 serializer = UserSerializer(data=request.data, context={'profile_img':request.FILES})
5 if serializer.is_valid():
6 serializer.save()
7 return Response({'message':'회원가입 성공'}, status=status.HTTP_201_CREATED)
8 else:
9 return Response({'message': serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
1 class UserSerializer(serializers.ModelSerializer):
2 """회원가입 페이지, 회원 정보 수정 페이지에서 사용되는 시리얼라이저입니다."""
3 class Meta:
4 model = User
5 fields = "__all__"
6
7 def create(self, validated_data):
8 user = super().create(validated_data)
9 password = user.password
10 user.set_password(password)
11 user.save()
12
13 profile_img = self.context['profile_img']
14 # print(profile_img)
15
16 for image_data in profile_img.getlist('profile_img'):
17 # print(image_data)
18 ProfileImage.objects.create(owner=user, profile_img=image_data)
19 return user
여기서 도저히 이해가 안가던 부분은 '[ 뷰 ]의 6번 row의 .save()'와 '[ 시리얼라이저 ]의 11번 row의 .save()'이 두 부분이었습니다. '왜 저장을 두 번이나 하지..?' 알아본 바로는 [ 뷰 ]에서 사용자가 보낸 데이터를 넣은 시리얼라이저의 유효성 검사를 하고 '.save()' 메서드가 발동되면 [ 시리얼라이저 ]의 'create'메서드와 'update'메서드가 둘 다 호출 되는데 'instance'의 유무에 따라 둘 중 한 메서드가 발동됩니다.
'.save()'메서드를 'ctrl+click'으로 들어가보면 'create'메서드와 'update'메서드를 확인할 수 있습니다. 우리는 이 함수들을 오버라이드하여 재정의한 메서드를 사용하는 것입니다.
def update(self, instance, validated_data):
raise NotImplementedError('`update()` must be implemented.')
def create(self, validated_data):
raise NotImplementedError('`create()` must be implemented.')
실제로 데이터베이스에 모델 객체를 저장하는 것은 [ 시리얼라이저 ]의 '.save()'부분에서 담당합니다.
추가적으로, [ 시리얼라이저 ] 내의 'super().create(validated_data)'부분의 'create' 메서드로 새 사용자 객체를 생성할 때, 기본적으로 모델을 생성하고 데이터베이스에 저장합니다. 저는 이게 비효율적이라고 생각하여 아래와 같이 코드를 짰습니다.
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
"""회원가입 페이지, 회원 정보 수정 페이지에서 사용되는 시리얼라이저입니다."""
class Meta:
model = User
fields = "__all__"
def create(self, validated_data):
# 사용자 모델을 직접 생성
user = User(**validated_data)
# 비밀번호 설정
password = user.password
user.set_password(password)
# 데이터베이스에 저장
user.save()
profile_img = self.context.get('profile_img')
if profile_img:
for image_data in profile_img.getlist('profile_img'):
ProfileImage.objects.create(owner=user, profile_img=image_data)
return user
위 코드에서 'User(validated_data)'를 사용하여 사용자 모델을 생성하고, 'user.save()'를 호출하여 데이터베이스에 저장합니다. 이렇게 하면 'super().create(validated_data)'를 사용하지 않고 원하는 대로 동작하며, 중복 저장 문제도 해결됩니다.
놓친 부분을 파악하고 코드를 고쳐 문제를 해결하는 점이 기록되어 있어 좋네요!