Notice
Recent Posts
Recent Comments
Link
Ssul's Blog
Django Serializer 이해하기(직렬화, 역직렬화) 본문
1. 내가 이해하는 직렬화, 역직렬화 구분
- A: 사람이 읽기는 어렵지만, 기계에게 효과적인 데이터(예: 0xB0, 0xA0)
- B: 사람이 읽기는 편하지만, 기계에게는 비효율적인 데이터(예: {"id": 1, "contents": '첫번째 글'})
직렬화: B -> A (dict -> bytes): 조금더 배우고나서 적음 > dict > byte
역직렬화: A -> B(bytes -> dict): 조금 더 배우고나서 적음: byte > dict > 객체
2. Django에서 직렬화 이해(GET과정)
DB에서 인스턴스 가져오기
ins0 = Comment.objects.all()[0]
serializer에 넣어서 dict객체로
sr = CommentSerializer(instance=ins0) #instance에 넣어준다
sr.data #dict형태
dict객체를 직렬화해서 bytes로 클라이언트에게 전달
JSONRenderer().render(sr.data)
#또는
Response(sr.data)
3. Django에서 역직렬화 이해(POST, UPDATE과정)
클라이언트에서 받은 요청(bytes)을 dict로 변환(viewsets또는 views.py에 있음)
tmpdata = JSONParser().parse(BytesIO(클라이언트요청))
#또는 보통 밑에 request 해결됨
tmpdata = request.data #request가 byte형태의 데이터를 > dict형태로
serializer에 넣어서 instance 생성 준비
dsr = CommentSerializer(data=tmpdata) #(중요)data에 넣는다, instance,data둘다 이용시 update
#해당 과정을 조금 더 디테일하게 들어가면, 댓글을 다는 과정에서
#CommentsModelViewSet.create() > get_serializer(data=request.data) 여기까지 진행
유효성 검사를 해서, 성공하면 validated_data생성
dsr.is_valid()
#통과하면 dsr.is_valid()는 True, dsr.errors는 {}
#그리고 dsr.validated_data에 통과된 최종 데이터들이 dict형태로 담김
인스턴스 생성(*인스턴스는 validated_data로 만든다)
instance = Comment(**dsr.validated_data)
instance.save()
#해당 과정을 조금 더 디테일하게 들어가면, 댓글을 다는 과정에서
#views.perform_create(serializer) -> serializer.save() -> serializer.create
4. APIView문서보면서 완벽히 이해하기(READ(GET):RetrieveAPIView, WRITE(POST):CreateAPIView)
READ(GET):RetrieveAPIView
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
#우리가 배운것처럼 DB에서 인스턴스 가져와서,
#시리얼라이저에 넣어서 dict
#그 dict를 Response로 bytes로 변환하여 전달 = JSONRenderer().render(~~~)
WRITE(POST):CreateAPIView
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
#클라이언트에서 받은 데이터 request.data를 시리얼라이저에 넣기
#is_valid로 유효성 검사
#perform_create *여기서 instance만들고, db저장
def perform_create(self, serializer):
serializer.save()
ModelSerializer
def save(self, **kwargs):
assert hasattr(self, '_errors'), (
'You must call `.is_valid()` before calling `.save()`.'
)
assert not self.errors, (
'You cannot call `.save()` on a serializer with invalid data.'
)
# Guard against incorrect use of `serializer.save(commit=False)`
assert 'commit' not in kwargs, (
"'commit' is not a valid keyword argument to the 'save()' method. "
"If you need to access data before committing to the database then "
"inspect 'serializer.validated_data' instead. "
"You can also pass additional keyword arguments to 'save()' if you "
"need to set extra attributes on the saved model instance. "
"For example: 'serializer.save(owner=request.user)'.'"
)
assert not hasattr(self, '_data'), (
"You cannot call `.save()` after accessing `serializer.data`."
"If you need to access data before committing to the database then "
"inspect 'serializer.validated_data' instead. "
)
validated_data = {**self.validated_data, **kwargs}
if self.instance is not None:
self.instance = self.update(self.instance, validated_data)
assert self.instance is not None, (
'`update()` did not return an object instance.'
)
else:
self.instance = self.create(validated_data)
assert self.instance is not None, (
'`create()` did not return an object instance.'
)
return self.instance
#self.instance가 있으면 update호출, 없으면 create호출
#그리고 호출사 validated_data 입력
#해당 내용은 Comment.objects.create(**validated_data)와 동일한 역할수행
def create(self, validated_data):
raise_errors_on_nested_writes('create', self, validated_data)
ModelClass = self.Meta.model
try:
instance = ModelClass._default_manager.create(**validated_data)
except TypeError:
tb = traceback.format_exc()
msg = (
'Got a `TypeError` when calling `%s.%s.create()`. '
'This may be because you have a writable field on the '
'serializer class that is not a valid argument to '
'`%s.%s.create()`. You may need to make the field '
'read-only, or override the %s.create() method to handle '
'this correctly.\nOriginal exception was:\n %s' %
(
ModelClass.__name__,
ModelClass._default_manager.name,
ModelClass.__name__,
ModelClass._default_manager.name,
self.__class__.__name__,
tb
)
)
raise TypeError(msg)
# Save many-to-many relationships after the instance is created.
if many_to_many:
for field_name, value in many_to_many.items():
field = getattr(instance, field_name)
field.set(value)
return instance
'dev > 까먹지마' 카테고리의 다른 글
SwiftUI에서 Markdown(마크다운) 표현하기 (0) | 2025.04.24 |
---|---|
swiftUI @StateObject, @ObservedObject, @EnvironmentObject 정리 (0) | 2025.04.18 |
AWS lambda에서 Layer구성(맥 실리콘-M1에서) (0) | 2024.08.08 |
도커(Docker)에서 쿠버네티스(k8s)까지: #1. Docker이해하기 (0) | 2024.05.23 |
python 맨날 까먹는 *arg **kwarg 이해하기 (0) | 2023.04.17 |