학습주제
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에도 반영이 된다.
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 함수를 이용해서 만일 넘겨받는 값이 없을경우, 기존 인스턴스 값을 반환하라고 되어있다.