class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
# fields = ['id', 'title', 'image', 'like', 'category']
class Meta:
에 model
과 fields
를 정해주는 방식으로 진행>>> from api2.serializers import *
>>>
>>> CommentSerializer()
CommentSerializer():
id = IntegerField(label='ID', read_only=True)
content = CharField(label='CONTENT', style={'base_template': 'textarea.html'})
create_dt = DateTimeField(label='CREATE DT', read_only=True)
update_dt = DateTimeField(label='UPDATE DT', read_only=True)
post = PrimaryKeyRelatedField(allow_null=True, queryset=Post.objects.all(), required=False)
model
과 fields
만 정의해줬지만, DRF 내부에서는 필드명
과 각 필드별 속성
을 자동으로 지정해서 사용함!필드명
과 필드별 속성
을 지정해서 사용할 줄 알아야 함! Form 클래스
: HTML <form>을 다루기 위해 만들어진 클래스Model 클래스
: DB Table을 다루기 위해 만들어진 클래스①직렬화 기능(Serialization)
과 ②유효성 검사 기능(Validation)
을 제공하고 있음!①직렬화 기능(Serialization)
과 ②유효성 검사 기능(Validation)
을 제공하는 클래스가 바로 DRF의 Serializer 클래스임!Form
, Model
, Serializer
클래스에 공통적으로 제공되는 것일까?JSON
Number
, String
, Object
, List
, Null
DRF에서 직렬화(serialize)하는 과정
>>> from api2.serializers import *
>>> CommentSerializer()
CommentSerializer():
id = IntegerField(label='ID', read_only=True)
content = CharField(label='CONTENT', style={'base_template': 'textarea.html'})
create_dt = DateTimeField(label='CREATE DT', read_only=True)
update_dt = DateTimeField(label='UPDATE DT', read_only=True)
post = PrimaryKeyRelatedField(allow_null=True, queryset=Post.objects.all(), required=False)
>>>
>>> from blog.models import *
>>> Comment.objects.all()
<QuerySet [<Comment: 첫번째 댓글 입니다>, <Comment: 두번째 댓글 입니다>, <Comment: 마스크 벗고 운동하>, <Comment: 댓글 생성 테스트 >, <Comment: 오랜만에 나이키 운>, <Comment: CSRF Token>, <Comment: ensure_csr>, <Comment: API 를 보기 위>, <Comment: DRF로 댓글 생성>, <Comment: CreateAPIV>]>
>>>
>>> c0 = Comment.objects.all()[0]
-> c0라는 레코드 객체는 DRF에서 'instance'라고 함!
instance
인자에 넣기!// CommentSerializer(instance=, data=)
// serialize할 때는 instance 인자에 넣음!
>>> sr = CommentSerializer(instance=c0)
// serializer의 data 속성 확인 (-> dict 자료형으로 변환됨)
>>> sr.data
{'id': 1, 'content': '첫번째 댓글 입니다.', 'create_dt': '2021-07-28T07:06:54.974180', 'update_dt': '2021-07-28T07:06:54.974180', 'post': 3}
// serializer의 data 속성의 Type 확인(ReturnDict -> DRF에서 기능을 추가한 dict 자료형)
>>> data0 = sr.data
>>> type(data0)
<class 'rest_framework.utils.serializer_helpers.ReturnDict'>
JSONRenderer
사용!
>>> from rest_framework.renderers import JSONRenderer
>>> JSONRenderer().render(data0)
b'{"id":1,"content":"\xec\xb2\xab\xeb\xb2\x88\xec\xa7\xb8 \xeb\x8c\x93\xea\xb8\x80 \xec\x9e\x85\xeb\x8b\x88\xeb\x8b\xa4.","create_dt":"2021-07-28T07:06:54.974180","update_dt":"2021-07-28T07:06:54.974180","post":3}'
>>> json0 = JSONRenderer().render(data0)
>>> type(json0)
<class 'bytes'>
-> ByteString이지만 한글이어서 16진수로 보임!
-> JSON 포맷으로 변환된 ByteString임!
인스턴스(=레코드 객체)
를 dict
로 변환한 후, 최종적으로 ByteString
으로 변환하여 client에게 보냄 → serialize 과정
DRF에서 역직렬화(deserialize)하는 과정
JSONParser
와 BytesIO
클래스 이용!>>> from rest_framework.parsers import JSONParser
// 주의! : JSONParser.parse() 메서드에 데이터를 직접 넣으면 에러 발생!
>>> JSONParser().parse(json0)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\drf-core\.venv\lib\site-packages\rest_framework\parsers.py", line 65, in parse
return json.load(decoded_stream, parse_constant=parse_constant)
File "C:\drf-core\.venv\lib\site-packages\rest_framework\utils\json.py", line 31, in load
return json.load(*args, **kwargs)
File "C:\Users\Jinhyung\anaconda3\lib\json\__init__.py", line 293, in load
return loads(fp.read(),
File "C:\Users\Jinhyung\anaconda3\lib\codecs.py", line 496, in read
newdata = self.stream.read()
AttributeError: 'bytes' object has no attribute 'read'
>>>
// BytesIO(json0) : ByteString 데이터를 JSON 데이터로 변경
>>> from io import BytesIO
>>> JSONParser().parse(BytesIO(json0))
{'id': 1, 'content': '첫번째 댓글 입니다.', 'create_dt': '2021-07-28T07:06:54.974180', 'update_dt': '2021-07-28T07:06:54.974180', 'post': 3}
>>>
>>> ddata0 = JSONParser().parse(BytesIO(json0))
>>> type(ddata0)
<class 'dict'>
data
인자에 넣기!// CommentSerializer(instance=, data=)
// 역직렬화(deserialize) 과정에서는 data 인자에 넣음!
>>> CommentSerializer(data=ddata0)
CommentSerializer(data={'id': 1, 'content': '첫번째 댓글 입니다.', 'create_dt': '2021-07-28T07:06:54.974180', 'update_dt': '2021-07-28T07:06:54.974180', 'post': 3}):
id = IntegerField(label='ID', read_only=True)
content = CharField(label='CONTENT', style={'base_template': 'textarea.html'})
create_dt = DateTimeField(label='CREATE DT', read_only=True)
update_dt = DateTimeField(label='UPDATE DT', read_only=True)
post = PrimaryKeyRelatedField(allow_null=True, queryset=Post.objects.all(), required=False)
유효성 검사
필요! : is_valid()
메서드 사용>>> dsr = CommentSerializer(data=ddata0)
>>> dsr.is_valid()
True
// 만약 유효성 검사에 통과하지 못하여 False가 리턴되면, 해당 값이 errors라는 dict 자료형에 담기게 됨!
>>> dsr.errors
{}
// 유효성 검사를 통과(True)한 데이터는 validated_data 속성에 담김
// DB에 넣을 instance를 만들 때는, 이 validated_data를 넣어서 만듦!
>>> dsr.validated_data
OrderedDict([('content', '첫번째 댓글 입니다.'), ('post', <Post: 유럽 여행 중 파리 개선문 다녀 왔답니다.>)])
// validated_data로 인스턴스 생성
>>> instance = Comment(**dsr.validated_data)
// 생성된 instance를 DB에 저장
>>> instance.save()
>>>
// check
>>> Comment.objects.all()
<QuerySet [<Comment: 첫번째 댓글 입니다>, <Comment: 두번째 댓글 입니다>, <Comment: 마스크 벗고 운동하>, <Comment: 댓글 생성 테스트 >, <Comment: 오랜만에 나이키 운>, <Comment: CSRF Token>, <Comment: ensure_csr>, <Comment: API 를 보기 위>, <Comment: DRF로 댓글 생성>, <Comment: CreateAPIV>, <Comment: 첫번째 댓글 입니다>]>
Serialize vs Deserialize 과정 비교
read
operation, 역직렬화(deserialize)과정을 write
operation이라고 함!GET
메서드 처리POST
, UPDATE
, DELETE
, PATCH
메서드 처리https://www.inflearn.com/course/%EC%9E%A5%EA%B3%A0-drf/dashboard