기본 회원가입 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 {}