오늘도 개발
Django Rest Framework 튜토리얼 따라하기 1. Serialization 본문
serialization(직렬화)이란?
데이터를 웹 통신이 가능한 형식으로 변환하거나,
웹 통신으로 받은 데이터를 프로그래밍 언어에서 사용할 수 형식으로 변환하는 것을 뜻한다.
장고에서 serialization은 파이썬 데이터를 JSON으로, JSON을 파이썬 데이터로 변환하는 것을 말한다.
직렬화가 필요한 이유는 파이썬 데이터를 웹 통신에 바로 사용할 수 없기 때문이다.
조립된 1000피스 퍼즐을 친구에게 택배로 보내주어야 한다고 생각해보자.
조립된 형태 그대로 주는 것보다, 분리해서 그림과 함께 상자에 담아 주는 것이 편리하다.
택배를 보내기 위해 퍼즐을 분리하는 것, 택배를 받은 후 조립하는 것이 직렬화이다.
models.py
from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted([(item, item) for item in get_all_styles()])
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
class Meta:
ordering = ['created']
serializers.py
DRF에서 serializer란? 직렬화할 데이터의 형태를 정의한 모양틀이다.
모델을 본따 serializer를 만들 수 있다. 하지만 모델과 serializer가 꼭 일치할 필요는 없다.
다음은 위의 models.py에서 정의한 Snippet 모델과 일치하는 serializer이다.
from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
class SnippetSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(required=False, allow_blank=True, max_length=100)
code = serializers.CharField(style={'base_template':'textarea.html'})
linenos = serializers.BooleanField(required=False)
language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')
# json 데이터를 파이썬 데이터로 변환한 후 db에 저장할 때 호출됨.
# 작성하지 않으면 db 저장 시 오류남.
def create(self, validated_data):
return Snippet.obects.create(**validated_data)
# json 데이터를 파이썬 데이터로 변환한 후 db에 저장할 때 호출됨.
# 작성하지 않으면 db 저장 시 오류남.
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.code = validated_data.get('code', instance.code)
instance.linenos = validated_data.get('linenos', instance.linenos)
instance.language = validated_data.get('language', instance.language)
instance.style = validated_data.get('style', instance.style)
instance.save()
return instance
이런 경우 ModelSerializer를 사용하면 코드를 단축할 수 있다.
create, update 메서드도 알아서 구현해주기 때문에 생략해도 된다.
fields에는 serializer에 사용할 모델의 필드를 적어주면 된다.
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ['id', 'title', 'code', 'linenos', 'language', 'style']
serializer의 모든 필드를 보려면(암묵적으로 생성된 필드 포함) repr를 사용하면 된다.
serializer = SnippetSerializer()
print(repr(serializer))
쉘에서 오브젝트를 serialization해보기
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
'''
snippet 오브젝트를 JSON으로 바꿔보기
'''
snippet = Snippet(code='abc')
# 1. snippet 오브젝트를 serializer에 넣기
serializer = SnippetSerializer(snippet)
print(serializer.data)
# {'id': 2, 'title': '', 'code': 'def', 'linenos': False, 'language': 'python', 'style': 'friendly'}
# 2. 결과물을 JSONRenderer로 json으로 바꾸기
json_data = JSONRenderer().render(serializer.data)
print(json_data)
# b'{"id":2,"title":"","code":"def","linenos":false,"language":"python","style":"friendly"}'
# 장고에서 GET 요청을 받아 클라이언트에게 데이터를 보낼 때 이런 형식으로 보내줘야 한다.
'''
JSON 데이터를 파이썬 오브젝트로 바꿔보기
'''
import io
stream = io.BytesIO(json_data)
python_data = JSONParser().parse(stream)
# 1. json 데이터를 serializer에 넣기
# data 키워드 인수를 사용해서 넣은 데이터는 사용 전 유효한지 확인하는 과정을 거치게 설계되어 있다.
# 따라서 외부에서 가져온 데이터가 유효한지 확인할 때(POST 요청 등) 사용하면 좋다.
serializer = SnippetSerializer(data=python_data)
# 2. is_valid()로 serializer로 변환된 데이터가 유효한지 검사(검사 안하고 데이터 가져오려고 하면 오류남)
# 유효한 경우 데이터가 validated_data에 저장됨
serializer.is_valid()
# 3. 변환된 데이터 확인
serializer.validated_data
# 4. 변환된 데이터를 db에 저장
# serializer에 정의된 create 메서드가 실행됨
serializer.save()
views.py
DRF의 view 기능을 사용하지 않는 버전
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.parsers import JSONParser
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
@csrf_exempt
def snippet_list(request):
if request.method == "GET":
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return JsonResponse(serializer.data, safe=False)
if request.method == "POST":
data = JSONParser().parse(request)
serializer = SnippetSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
return JsonResponse(serializer.errors, status=400)
@csrf_exempt
def snippet_detail(request, pk):
try:
snippet = Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
return HttpResponse(status=404)
if request.method == "GET":
serializer = SnippetSerializer(snippet)
return JsonResponse(serializer.data)
elif request.method == "PUT":
data = JSONParser().parse(request)
serializer = SnippetSerializer(data=data)
if serializer.is_valid():
# serializer의 create이나 update 메서드가 호출됨
serializer.save()
return JsonResponse(serializer.data)
return JsonResponse(serializer.errors, status=400)
elif request.method == "DELETE":
snippet.delete()
return HttpResponse(status=204)
참고
https://www.django-rest-framework.org/tutorial/1-serialization/
'웹 프로그래밍 > Django' 카테고리의 다른 글
| Django Rest Framework 튜토리얼 따라하기 3. authentications and permissions (0) | 2023.01.08 |
|---|---|
| Django Rest Framework 튜토리얼 따라하기 2. view 쉽게 작성하기 (0) | 2023.01.08 |
| Django ORM 최적화 - select_related, prefetch_related (0) | 2022.08.05 |
| Django로 Unit Test해보기 (0) | 2022.08.05 |
| Django 앱 세팅하는 법 (0) | 2022.07.17 |