기본 회원가입 API를 작업하면서 조금씩 맛보고 있는 DRF - serializer 기능과 APIview에 대해 기초 정리.
클라이언트-서버가 데이터를 주고받음에 있어서 문제가 없도록 serialize & deserialize 해주는 기능이다.
모델링을 create/update 할 때, python 데이터타입으로 변환하여 그대로 메모리에 저장하는 것이다.
결국, 데이터 구조나 객체를 다른 컴퓨터 환경에서도 저장하고 재구성할 수 있도록 포맷을 변환하는 작업이라고 할 수 있다.
django에서는 Form이 유사한 역할을 하지만, 결정적으로 아래의 차이가 있다.
Form : html tag를 생성serializer : JSON을 생성
공식문서의 예시를 보자.
from datetime import datetime
class Comment:
def __init__(self, email, content, created=None):
self.email = email
self.content = content
self.created = created or datetime.now()
comment = Comment(email='leila@example.com', content='foo')
이를 serializing 하면 아래와 같다.
from rest_framework import serializers
class CommentSerializer(serializers.Serializer):
email = serializers.EmailField()
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
이제 맨 처음에 선언한 comment를 CommentSerializer에 담아보자.
serializer = CommentSerializer(comment)
serializer.data
# {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}

예시 코드는 아래와 같다.
serializer = CommentSerializer(data=data)
serializer.is_valid()
# True
serializer.validated_data
# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}
Deserializing 할 때는, data에 데이터를 넣어 전달한다. is_valid()를 통해 유효성 검사를 진행validated_data에 담긴다.#serializer.py
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from .models import User
class UserSerializer(serializers.Serializer):
email = serializers.EmailField(validators = [UniqueValidator(queryset = User.objects.all())])
last_name = serializers.CharField(max_length = 50, write_only = True)
first_name = serializers.CharField(max_length = 50, write_only = True)
password = serializers.CharField(max_length= 128, write_only = True)
def create(self, validated_data):
return User.objects.create_user(**validated_data)
UniqueValidator를 사용해서, 기존 DB에 있는 email인지 아닌지 확인할 수 있다 write_only 속성을 통해 response 시(serializing할 때) 나타나지 않도록 했다. 위 serializer를 기반으로, view는 아래와 같이 작성되었다.
#views.py
from rest_framework.permissions import AllowAny
from rest_framework.generics import CreateAPIView
from .serializers import UserSerializer
class SignUpView(CreateAPIView):
permission_classes = [AllowAny]
serializer_class = UserSerializer
post만 처리하는 handlerpermission_classes를 통해 회원가입은 모두가 접근할 수 있도록 했다UserSerializer를 seriazlier_class에 담아 실행시키면, 검증과정 후에 post까지 실행되어 DB에 저장된다. CreateAPIView의 code를 보면, 아래와 같이 정의되어 있어 가능한 것. (is_valid, perfrom_create() 등이 모두 설정되어 있다)
사수께서 CreateAPIView를 사용했기 때문에 post 함수도 작성할 필요 없어요~ 라고 했을 때 동공지진 일으키며 지웠는데 정말 작동했고 너무 신세계였다...
#CreateAPIView
class CreateAPIView(mixins.CreateModelMixin,GenericAPIView):
"""
Concrete view for creating a model instance.
"""
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
#def create()
class CreateModelMixin(object):
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}