송신자 : 객체를 문자열로 변환하여, 데이터 전송 → 직렬화
수신자 : 수신한 문자열을 다시 객체로 변환하여, 활용 → 비직렬화
보통의 웹 세상에서는 …
요즘의 API 서버에서는 대개 JSON 인코딩된 요청/응답
from rest_framework.renderers import JSONRenderer
data = Post.objects.all()
JSONRenderer().render(data)
# forms.py
from django.forms import ModelForm
from .models import Post
class PostForm(ModelForm):
class Meta:
model = Post
fields = '__all__'
# serializers.py
from rest_framework.serializers import ModelSerializer
# Post모델에 대한 ModelSerializer 정의
class PostModelSerializer(ModelSerializer):
class Meta:
model = Post
fields = '__all__'
post = Post.objects.first() # Post 타입
serializer = PostModelSerializer(post)
serializer.data # -> ReturnDict 타입
class ReturnDict(OrderDict):
def __init__(self, *args, **kwargs):
self.serializer = kwargs.pop('serializer')
super().__init__(*args, **kwargs)
....
qs = Post.objects.all()
serializer = PostModelSerializer(qs, many=True)
serializer.data # list와 OrderedDict의 조합
# 파이썬 기본 JSON 변환 사용 활용
import json
json_str_string = json.dumps(serializer.data, ensure_ascii=False)
# DRF에서 지원하는 JSON 변환 활용 à 변환 Rule이 추가된 Encoder
from rest_framework.renderers import JSONRenderer
json_utf8_string = JSONRenderer().render(serializer.data)
→ 지정이 맞지 않으면 변환 에러 발생 (TypeError, AttributeError)
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
# ...
def to_representation(self, instance):
"""
Object instance -> Dict of primitive datatypes.
"""
ret = OrderedDict()
fields = self._readable_fields
for field in fields:
try:
attribute = field.get_attribute(instance)
except SkipField:
continue
# We skip `to_representation` for `None` values so that fields do
# not have to explicitly deal with that case.
#
# For related fields with `use_pk_only_optimization` we need to
# resolve the pk value.
check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
if check_for_none is None:
ret[field.field_name] = None
else:
ret[field.field_name] = field.to_representation(attribute)
return ret
qs = Post.objects.all()
# JsonResponse 생성자의 각종 인자 나열
encoder = MyJSONEncoder
safe = False # True: data가 dict일 경우, False: dict이 아닐 경우
json_dumps_params = {'ensure_ascii': False}
kwargs = {} # HttpResponse에 전해지는 Keyword 인자
from Django.http import JsonResponse
response = JsonResponse(qs, encoder, safe, json_dumps_params, **kwargs)
qs = Post.objects.all()
serializer = PostModelSerializer(qs, many=True)
from rest_framework.response import Response
response = Response(serializer.data) # Content-Type: text/html 디폴트 지정
from rest_framework.views import APIView
renderer_cls = APIView.renderer_classes[0]
renderer_obj = renderer_cls()
response.accepted_renderer = renderer_obj # JSON 변환을 위한 JSONRenderer 인스턴스
response.accepted_media_type = renderer_obj.media_type # 'application/json'
response.renderer_context = {'view': None, 'args': (), 'kwargs': {}, 'request': None}
response # <Response status_code=200, "application/json">
from rest_framework import generics
class PostListAPIView(generics.ListAPIView):
queryset = Post.objects.all()
serializer_class = PostModelSerializer
post_list = PostListAPIView.as_view()
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
username = serializers.ReadOnlyField(source='author.username') # 추가
class Meta:
model = Post
fields = ['pk', 'username', 'title', 'cotnent'] # 'username' 추가
통해서도 구현 가능
from django.contrib.auth import get_user_model
from rest_framework import serializers
from .models import Post
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = get_user_model()
fields = ['username']
class PostSerializer(serializers.ModelSerializer):
author = AuthorSerializer()
class Meta:
model = Post
fields = '__all__'