Django DRF - Serializer

데이터 가공기계

by 내가 사는 세상

고객과 서버 사이에선 수많은 데이터 전송이 벌어진다. 이때 보내주고 받을 데이터를 가공, 정제하는 작업을 Serializer라는 것이 하게 된다. 그래서 serializers.py의 주된 기능은 다음 2가지 이다.


1. 직렬화(serialize) / 역직렬화(deserialize)

2. 검증(validation) 기능





'고객한테 보내줄 데이터(파이썬 개체)'를 선별한 뒤, JSON(형식을 갖춘 문자열)으로 형태를 바꿔주는 것을 직렬화한다고 한다.

반대로 '고객이 보내준 데이터(JSON)'를 '파이썬 개체'로 바꿔 DB에 저장하는 것을 역직렬화라고 한다.

trrr.png
fwefwfew.png

직렬화 : 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()




나만의 serializer.py를 만들 때 자주 사용하는 함수들


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): 이게 필요하다




Tips


- class Meta:

fields = ['어쩌구']

에 정의된 값들은 또다시 필드로 정의해줄 필요가 없다.




Foreign key로 연결된 것을 id가 아닌 다른 값으로 불러들이고 싶을 때


class ProductListSerializer(ModelSerializer):
# Category 모델의 pk 아닌 name 추출 - Foreign
category = serializers.CharField(source='category.name')


233.png




Nested Serializer


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 파이썬

keyword
매거진의 이전글Django - static, media