DB에 저장된 데이터를 직렬화하여 JSON형태로 바꾸기 쉬운 파이썬 데이터타입으로 변환해줍니다. JSON파일을 이용해 데이터를 주고받게 되면 시스템/언어에 구애받지 않고 사용이 가능하며 가볍다는 장점이 있습니다.
+serialize, deserialize, 데이터 검증하는 기능을 수행합니다
class BaseSerializer(Field):
def __init__(self, instance=None, data=empty, **kwargs):
# 생략
class Serializer(BaseSeializer):
첫번째 인자가 인스턴스이므로 데이터를 전달할 때는 data=
이 꼭 필요하다
serializer = PostSerializer(reqeust.data) # 오류
# 인스턴스는 첫번째 인자이므로 전달할 때 키워드가 필요없다
serializer = PostSerializer(post)
serializer = PostSerializer(data=request.data)
# 첫번째 인자가 있으면 두번째가 구분이 되어 키워드가 필요없다
serializer = PostSerializer(post, data=reqeust.data)
serializer = PostSerializer(post, reqeust.data)
serializers.ModelSerializer를 상속받으면 아래처럼 시리얼라이저에서 필드 정의하는 과정이 불필요함
# serializers.py
from rest_framework import serializers
class SnippetSerializer():
id = IntegerField(label='ID', read_only=True)
title = CharField(allow_blank=True, max_length=100, required=False)
style = ChoiceField(choices=[('autumn', 'autumn'), ('borland', 'borland'), ('bw', 'bw'), ('colorful', 'colorful')...
# 또는
# class SnippetSerializer(serializers.Serializer):
# title = serializers.CharField()
# content = serializers.TextField()
사용
# views.py
from snippets.serializers import SnippetSerializer
serializer = SnippetSerializer()
print(repr(serializer))
데이터 통신을 위해서는 데이터가 바이트 타입
으로 변환되어야하는데 시리얼라이즈를 통해 바이트 타입으로 변환된 데이터는 JSON으로 쉽게 변환할 수 있으며 디시리얼라이즈도 마찬가지이다.
또한 XML보다 가볍고 특정 언어에 종속되지 않아서 타 어플리케이션과 데이터를 주고받기가 좋다는 장점이 있다. 딕셔너리 형태의 구조와 단순한 문자열로 이루어져있다는 점 또한 시스템 및 인간 모두가 이해하기 좋다는 장점이 된다.
JSON->JSONDataHandler->byte[]
ForiegnKey
의 관계에 있는 모델의 필드를 사용할 때는 해당 필드를 사용하고자 하는 시리얼라이저 클래스 안에서 SerializerMethodField
를 통해 가져오고 get_해당 필드명(self,object)
함수를 시리얼라이저 클래스 안에 정의해서 필드에 해당하는 객체를 리턴해주고 Meta
클래스의 fields=
에 추가해줍니다. 이때 시리얼라이저 안에서의 필드명과 가져오는 함수의 메소드명은 원하는대로 설정이 가능합니다.
foreignkey필드에 명시된 related_name이 없다면 기본적으로 모델_set
을 시리얼라이져 메타 클래스의 fields에 명시해주면 사용할 수 있습니다.
# models.py
class Album(models.Model):
album_name = models.CharField(max_length=100)
artist = models.CharField(max_length=100)
class Track(models.Model):
album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)
order = models.IntegerField()
title = models.CharField(max_length=100)
duration = models.IntegerField()
class Meta:
unique_together = ['album', 'order']
ordering = ['order']
def __str__(self):
return '%d: %s' % (self.order, self.title)
Track 이 Album을 정참조 -> Album을 Track 이 역참조
모델 간의 관계에서 다(多)에 해당하는 필드라면 many=True
옵션을 넣어줘야한다
정참조
tracks가 표현되는 형태에 따라서 종류가 나뉨
StringRelatedField
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.StringRelatedField(many=True) # read only.
PrimaryKeyRelatedField
HyperlinkedRelatedField
SlugRelatedField
slug_field=
에 명시된 track의 필드에 해당되는 값으로 tracks에 nested되어 표현됨tracks = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='title'
)
referred entity be embedded/nested in the representation of the objects that refers to it
역참조 관계는 모델 필드에 정의한 related_name이나 따로 정의한 related_name이 없다면 모델_set
를 시리얼라이저 클래스 내부에 있는 Meta 클래스 fields=
에 써준다
class AlbumSerializer(serializers.ModelSerializer):
class Meta:
fields = ['track_set', ...]
https://www.django-rest-framework.org/api-guide/relations/
validate()
함수를 통해 다수의 필드에 대해 검사합니다 - 검사 내용을 한번에 작성할 수 있음
class PostSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
def validate(self, data):
if '제목' not in data['title']:
raise ValidationError('제목이라는 말이 들어가야 합니다.')
return data
# serializers.py
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
class PostSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
def validate_title(self, value):
if '제목' not in value:
raise ValidationError('제목이라는 말이 들어가야 합니다.')
return value
built-in validator들이 모든 케이스를 커버하지 못하기 때문에 필요한 상황에 맞춰 custom validator를 짜야한다.
조건문으로 오류 케이스를 작성한 후 raise ValidationError()
내부에 오류 메세지를 작성합니다
is_valid()
로 검증된 validated_data
를 받아서 .save()
호출시 인스턴스가 있으면 update()를 통해 저장하고 없으면 create를 통해 인스턴스 생성 후 저장
https://seoyoung2.github.io/django/2020/08/16/Serializer.html
import sys
T=int(input())
for t in range(T):
n=int(sys.stdin.readline())
dp = [0]*(n+1) # 0부터 계산하므로 n개까지 하면 list index out of range
for i in range(1,len(dp)):
dp[i]=dp[i-3]+dp[i-2]+dp[i-1]
if i<4: # 1-3까지
print(i)
dp[i]+=1 # 자기 자신만으로도 완성하는 경우가 추가됨
print(dp[n])
print(dp) # n=5일 때 [0, 1, 2, 4, 7, 13]
DP는 경우의 수를 어느정도 계산해보고 패턴을 찾아야하는 것 같다
반복되는 부분이 전체를 만들 때 DP로 문제를 푼다는데 for문이나 재귀를 통해서 구현할 수 있다는데 일단 for문을 이용해서 구현하는 방법
n+1까지 만들어야 n개까지 모두 저장할 수 있어서 초기 dp리스트는 n+1 크기로 만들어야하고 1-3까지는 자기 숫자로도 만들 수 있어서 +1을 해줘야한다