요즘따라 더 자주 느끼는것이지만, 예전에 열심히 공부를하더라도 꼼꼼히 생각을 기록해두지 않으면 모두 잊게된다는 것입니다 😓 시리얼라이저를 활용해보고 싶은데, 너무 기억이 가물가물해서 이번 기회에 확실히 개념을 정리해보고자 합니다.
시리얼라이저란 DRF
의 핵심 구성 요소로, Django 모델이나 쿼리셋과 같은 복잡한 데이터를 JSON 형식으로 변환하는 역할을 수행합니다. 이 과정을 직렬화라고 합니다.
마찬가지로, 시리얼라이저는 JSON 데이터를 Python 데이터 유형으로 변환하는 역직렬화(deserialization)
를 가능하게 합니다. DRF의 시리얼라이저는 Django의 폼과 유사한 역할을 하지만, HTML 폼 데이터 대신 JSON 데이터를 처리합니다.
소스 코드를 저장하기 위한 Post 모델을 정의해봅시다. 앞으로 계속 이 모델을 사용하여 설명할 것입니다. 참고로 장고에서 모델을 정의할 때 Primary Key로 명시한 필드가 없다면 자동으로 Primary Key로서 id 필드가 정의됩니다. 데이터베이스에 모델 인스턴스가 저장될 때마다 id 필드의 값은 1씩 증가합니다. 따라서 아래의 Snippet 모델은 실제로 7개의 필드를 가지고 있다고 생각해야 합니다.
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 Post(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']
시리얼라이저에는 직렬화, 역질렬화 되어야 하는 모델의 필드들이 정의됩니다. 대응하는 모델의 모든 필드들을 정의할 수도 있고, 일부 필드만 정의할 수도 있습니다. 여기에서 정의되는 필드의 값들은 시리얼라이즈 시 JSON 데이터로 표현할 때 사용이 되며, 디시리얼라이즈 시 DB 인스턴스를 생성하거나 수정할 때 사용이 됩니다.
그리고 시리얼라이저에는 create()
메소드와 update()
메소드를 정의해줘야 합니다. create() 메소드는 시리얼라이저를 대상으로 save() 메소드를 호출함으로써 DB 인스턴스를 생성하고자 할 때의 동작을 정의해야 하고, update() 메소드는 시리얼라이저를 대상으로 save() 메소드를 호출함으로써 DB 인스턴스를 수정하고자 할 때의 동작을 정의해야 합니다.
from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
class PostSerializer(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')
def create(self, validated_data):
return Snippet.objects.create(**validated_data)
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
장고가 Form 클래스에 대응하는 ModelForm 클래스를 제공하는 것과 마찬가지로, DRF도 Serializer 클래스에 대응하는 ModelSerializer
클래스를 제공합니다. ModelSerializer는 특별한 것이 아닙니다. 그저 시리얼라이저를 더욱 편하게 정의할 수 있도록 리팩토링을 해줄 뿐입니다.
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ['id', 'title', 'code', 'linenos', 'language', 'style']
// ....
from snippets.serializers import SnippetSerializer
serializer = SnippetSerializer()
print(repr(serializer))