Django Shell에서 Serializer 사용하기

data_hamster·2023년 4월 26일
0

학습주제
Django Shell에서 Serializer 사용하기

학습내용
지난 시간에 만든 QuestionSerializer을 장고 쉘에서 활용해 보기로 한다.
시리얼라이저에서 update 되었다는 것을 알게 하기 위해
instance.question_text = validated_data.get('question_text', instance.question_text) +'[시리얼라이저에서 업데이트]'

라고 정의한다.

from polls_api.serializers import QuestionSerializer
가 계속 인식이 안됐는데, 장고 쉘은 켠 상태에서 내가 수정을 했기 때문이다. 장고 쉘은 수동으로 껐다 다시 켜줘야 새로운 정보가 반영된다.


임의의 오브젝트 q 생성.

이제 시리얼라이저를 만들어 본다.

Serializer 클래스를 상속받아서, 인스턴스를 집어넣으면 알아서 초기 값을 잘 생성해준다.
serializer.data로 생성된 값을 확인할 수 있다. 딕셔너리 형태로 생성된 것을 확인할 수 있다.
이 값들을 JSON 형태로 바꾸기 위해서는 JSON renderer를 가져와야 한다.
from rest_framework.renderers import JSONRenderer

JSON을 만들어본다.
json_str = JSONRenderer().render(serializer.data)


보면 한글부분이 인코딩되어 있고, 영어부분은 잘 뜬다. 기존 값과 큰 차이가 없어보이지만, string 형태로 만들어 진 것임.

이러한 string 형태의 JSON 데이터를 서버가 받았다면 서버는 이 JSON을 활용해서 deserialize를 하고 업데이트를 하거나, create을 한다. 이번엔 역순의 작업을 한다. 이러한 string을 다시 JSON으로 바꾸어 본다.

import json

data = json.loads(json_str)
처음에 넣었던 데이터로 돌아온 것을 확인할 수 있다.

Question 내용 --> JSON 형태 -> string 형태 이 과정을 serialize라고 한다.

string -> JSON -> Question 인스턴스
JSON의 내용을 모델에 로드까지 해야 deserialize가 끝났다고 할 수 있음.

QuestionSerializer는 serialize, deserilize 모두 지원하므로, JSON 형태를 data에 넣어준다.
serializer = QuestionSerializer(data=data)

serializer.is_valid()를 통해 정합성 테스트를 한다.

이 valid data를 이용해 새로운 모델을 만들예정. 그 전에
serializer.validated_data


OrderedDict 형태로 출력. 그러나 id, pub_date가 보이지 않는다. 왜냐하면 두 속성은 read_only이기 때문이다.
이걸 이용해서 save를 한다.
serializer.save()를 호출하면 이 serializer는 이 상황이 create을 해야하는지, update를 해야하는지 판단하게 된다. 이미 만들어진 인스턴스가 없다면, serializer는 create을 하고, 만들어진 인스턴스가 있었다면 update를 한다. 우리가 처음으로 가면
serializer = QuestionSerializer(data=data)
이렇게 데이터만 넘겨준 상황. 인스턴스를 주지 않았음.
따라서 .save()시 create가 동작함. create를 하면 새로만든 오브젝트가 리턴됨. 이에 리턴된 오브젝트를 받을 수 있게 앞에 변수를 선언한다.

날짜도 새롭게 지금 시점으로 생성된 것을 확인할 수 있다. 그렇다면 id값은 어떻게 됐을까?

id도 잘 생긴 것을 확인할 수 있었다. 그럼 data로 넘겨줄 때 id 값 1은 사용하지 않았다는 것이 된다.
Question.objects.all()을 통해 같은 제목이 2개가 생긴 것을 확인할 수 있다.

new_question의 제목을 업데이트 해보고자 한다.
data = {'question_text':'제목수정'}
serializer = QuestionSerializer(new_question, data=data)

validated_data를 호출하자 오류가 난다. 그 전에 is_valid()를 거쳐야 하기 때문.

.save()도 마찬가지로 is_valid()를 거쳐야 한다.

serializer.save()를 하면 이번엔 update로 가게된다. 인스턴스 new_question을 넘겨주었기 때문.
![](https://velog.velcdn.com/images/kjw9684/post/4361fd3a-3dee-435e-bc3f-87271eded8ab/image.png)
question이 리턴됨. 날짜는 기존의 날짜를 유지함.

serializer.save()하면 바로 DB에도 반영이 된다.

validation이 통과하지 못하는 상황

long_text = "abcd"*300 long_text 'abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd'

상당히 긴 텍스트를 question_text 값으로 할당
data = {'question_text':long_text}
serializer = QuestionSerializer(data=data)

serializer.is_valid() -> False가 나왔다. False에 대한 이유는 serializer.errors에서 확인 가능하다.

필드가 200자를 넘는지 확인하라고 한다. serializer.validated_data를 보면

출력은 되나, 비어있다. (일단 is_valid()를 수행했으므로) 지금은 1:1 로 통과를 실패했지만 여러개의 필드값 중에서 부분적으로 통과한 경우도 생각해 볼 수 있다.
serialize.py로 넘어가서 인스턴스를 넣어줬을 경우 대응하는 update를 보면,

딕셔너리의 get 함수를 이용해서 만일 넘겨받는 값이 없을경우, 기존 인스턴스 값을 반환하라고 되어있다.

절차

profile
반갑습니다 햄스터 좋아합니다

0개의 댓글