데이터 가공기계
고객과 서버 사이에선 수많은 데이터 전송이 벌어진다. 이때 보내주고 받을 데이터를 가공, 정제하는 작업을 Serializer라는 것이 하게 된다. 그래서 serializers.py의 주된 기능은 다음 2가지 이다.
1. 직렬화(serialize) / 역직렬화(deserialize)
2. 검증(validation) 기능
고객한테 보내줄 데이터를 선별한 뒤, json으로 형태를 바꿔주는 것을 직렬화한다고 한다.
반대로 고객이 보내준 데이터를 파이썬 객체로 DB에 저장하는 것을 역직렬화라고 한다.
직렬화 : INSTANCE -- serializer--→ DICT(사전) → BYTES STRING(JSON형태)
: serializer.data => dict형태
역직렬화 : BYTES STRING(JSON형태) --- bytesio --→ DICT(사전) --- serializer --→ INSTANCE
b= Serializer(data=data)
b.is_valid()
b.validated_data
binstance = AModel(**a.validated_data)
binstance.save()
def create(self, validated_data)
: views.py에서 perform_create() -> serializer.save()에서 시작된 것
: ModelSerializer에서
instance = ModelClass._derault_manager.create(**validated_data)
를 통해 파이썬 객체(모델 인스터스)를 만들어서 DB에 저장하는 것
https://github.com/encode/django-rest-framework/blob/master/rest_framework/serializers.py#L178
def update(self, instance, validated_data)
: views.py에서 perform_create() -> serializer.save()에서 시작된 것
https://github.com/encode/django-rest-framework/blob/master/rest_framework/serializers.py#L175
def validate(self, attrs):
: serializer 필드라는 재료들을 통해 무언가 검증작업이 필요하다면 사용
: ex) password = password2 검증,
: serializer.validated_data를 하면 return 값이 def validate(self, attrs)의 리턴값이다
def save(self, **kwargs):
이를 사용한 예시를 보자.
# serializers.py
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date']
def create(self, validated_data):
return Book.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.author = validated_data.get('author', instance.author)
instance.publication_date = validated_data.get('publication_date', instance.publication_date)
instance.save()
return instance
def validate_title(self, value):
if not value:
raise serializers.ValidationError("Title cannot be empty.")
return value
def validate_publication_date(self, value):
from datetime import date
if value > date.today():
raise serializers.ValidationError("Publication date cannot be in the future.")
return value
def save(self, **kwargs):
return super().save(**kwargs)
class LoginSerializer(serializers.Serializer):
email = serializers.EmailField(min_length=3, max_length=255)
password = serializers.CharField(min_length=3, max_length=68, write_only=True)
username = serializers.CharField(min_length=1, max_length=255, read_only=True)
tokens = serializers.SerializerMethodField()
def get_tokens(self, obj):
user = User.objects.get(email=obj['email'])
return {
'refresh': user.tokens()['refresh'],
'access': user.tokens()['access']
}
class Meta:
model = User
fields = ['email', 'password', 'username', 'tokens']
email, password, username, tokens처럼 정의하면 #이 4가지를 가공기에 넣어서 변환시킨 뒤, 고객에게 보내줄 의도이다
tokens = serializers.SerializerMethodField()
여기선 def get_tokens(self, obj): 이게 필요하다
- class Meta:
fields = ['어쩌구']
에 정의된 값들은 또다시 필드로 정의해줄 필요가 없다.
class ProductListSerializer(ModelSerializer):
# Category 모델의 pk 아닌 name 추출 - Foreign
category = serializers.CharField(source='category.name')
from rest_framework import serializers
from .models import Post, Comment
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ['id', 'author', 'text']
class PostSerializer(serializers.ModelSerializer):
comments = CommentSerializer(many=True, read_only=True)
class Meta:
model = Post
fields = ['id', 'title', 'content', 'comments']
공식문서 : https://www.django-rest-framework.org/api-guide/serializers/
김석훈 : Django REST Framework 핵심사항
권태형 : 백엔드를 위한 Django REST Framework with 파이썬