본문 바로가기
관리자

Programming-[Backend]/Django

Django REST framework 공식문서: 1. Serializer - view와 serializer관계, 전달 정보 : Data, create/update, save

728x90
반응형

DRF 공식문서 스터디 기록. 일반적이고 기본적인 내용은 생략하고, 새롭게 배운 내용과 실무에서 쓰일만한 내용 위주로 공부한다.

DRF 공식문서의 API Guide 부분을 참고했다.

https://www.django-rest-framework.org/

 


Serializer의 역할 

Serialize를 한다는 것은 일반적으로는 특정 언어에서 사용하는 객체를 바이트 또는 스트림으로 변환한다는 것이다. Django 에서는 Django가 다룰 수 있는 객체를 외부에서 받는 JSON 등의 데이터 형태로 변환한다는 것을 의미한다. Deserialize는 그와 반대 개념이다.

 

요청 JSON 등의 데이터 -> Deserialize -> Django 객체(DB 저장)-> Serialize -> 응답 JSON 등의 데이터

 

Serializer에서 serializer와 deserialize 두 기능을 한꺼번에 제공한다.

 

 

 

 

DRF 기본 구조 개략도

 

대략적으로 파악한 내용. 정확하지 않을 수 있으니 유의

 

 

Serializer.data

 

필드 정의 및 data값 조회

serializer를 정의하고 Model 객체를 넣으면, serializer.data에 해당 모델을 serialize한 데이터가 담긴다.

 

from rest_framework import serializers

class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()
serializer = CommentSerializer(comment)
serializer.data
# {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}

 

참고사항

CommentSerializer를 만들 때 필드값은 해당하는 모델인 Comment에 없는 값을 정의해도 된다. 다만 이렇게 정의하고 comment = Comment(...)으로 만들어서 serializer의 인자로 넘기면, serializer.data로 조회 시 'object has no attribute' 에러를 반환한다.

 

JSONRenderer : json으로 변환하기

from rest_framework.renderers import JSONRenderer

json = JSONRenderer().render(serializer.data)
json
# b'{"email":"leila@example.com","content":"foo bar","created":"2016-01-27T15:17:10.375877"}'

JSONRenderer 라는게 있고, serializer.data를 넘기면 json 형식으로 serialize 해준다.

 

JSONParser: Python native datatype으로 변환하기

이후 io.BytesIO, JSONParser를 이용해서 serialize가 가능하다.

 

import io
from rest_framework.parsers import JSONParser

stream = io.BytesIO(json)
data = JSONParser().parse(stream)

 

 


 

serializer.save()

 

create or update

특정 Model의 instance를 저장 또는 업데이트하기 위해 serializer.save()를 호출한다. Serializer를 초기화 하는 단계에서 save()의 인자로 어떤 instance가 전달되면 update, 그게 아니라 data만 전달된다면 create 메서드가 실행된다.

 

# .save() will create a new instance.
serializer = CommentSerializer(data=data)

# .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data)

 

추가 인자 전달하기

view 쪽에서 serializer 쪽으로 추가 인자를 전달할 수도 있다. 공식문서에서는 anything else that is not part of the request data. 라고 표현되어 있다. 즉 request에서 오는 정보 외에 다른 정보를 추가로 전달해주는 목적으로 사용한다.

 

serializer.save(owner=request.user)

 

validated_data

재밌는 것은 이렇게 Serializer로 추가로 전달된 데이터는 validated_data 인자 속에서 조회할 수 있다고 설명되어 있다는 것이다. view -> serializer로 data -> validated_data로 넘어가는 구조인데, view에서의 data와 관련없이 추가적으로 전달한 정보도 validated_data에 담긴다는 것이 약간은 모순적으로 느껴진다. 검증이 되지 않은 정보가 validated_data라는 이름의 객체에 담기는 것이다.

 

이것은 다시 표현해보면, 클라이언트(프론트엔드)에서 넘어오는 body 정보는 view의 data에 request.data로 담아서 validate를 거치게 하고, 나머지 서버(백엔드)에서 추가적으로 넘겨주는 데이터는 serializer.save() 안에 담아서 별도의 검증과정 없이 validated_data 객체로 넘기는 개념이다.

 

 

.save() 직접 overriding 가능

serializer 내부에서 .create나 .update에 로직을 작성하도록 되어있어서, 실행하는 로직이 꼭 create나 update와 관련없는, 예를 들어 그냥 이메일을 보내는 상황이면 의미적으로 메서드 이름이 맞지 않을 수 있다. 이러한 경우 save 자체를 overriding할 수도 있다. 이 때도 사용할 데이터는 validated_data에서 가져와서 쓰면 된다.

 

class ContactForm(serializers.Serializer):
    email = serializers.EmailField()
    message = serializers.CharField()

    def save(self):
        email = self.validated_data['email']
        message = self.validated_data['message']
        send_email(from=email, message=message)

 

좀 더 세밀히 살펴봐야할 것이, save() 메서드 자체가 이메일을 보내는 기능을 한다기보단, save() 메서드 내부에 send_email()이라는 메서드를 다시 정의한 구조이다. 즉 create나 update를 하고 validated_data를 사용하는 구조라면 반드시 save() 메서드를 실행해야하는 것으로 이해된다.

 

728x90
반응형