[DRF] django SET_NULL 옵션과 시리얼라이저 저장, 그리고 테스트코드 immutable QueryDict

Yungsang Hwang·2022년 7월 15일
1

Django-Rest-Framework

목록 보기
14/15

django SET_NULL 옵션과 시리얼라이저 저장, 그리고 테스트코드 immutable QueryDict

django SET_NULL 옵션과 시리얼라이저 저장, 그리고 테스트코드 immutable QueryDict

  • immutable QueryDict 오류
  • 기존의 QnAAnswer 모델은 on_delete 옵션이 CASCADE 였다.
# 변경 전 코드
class QnAAnswer(models.Model):
	user = models.ForeignKey(UserModel, verbose_name="답변자", on_delete=models.CASCADE)
	question = models.ForeignKey(QnAQuestion, verbose_name="질문", on_delete=models.CASCADE)
	content = models.TextField("답변")
	like = models.ManyToManyField('user.User', related_name="answer_like", through="AnswerLike")
	is_selected = models.BooleanField("채택여부")
# 변경 전 코드
class AnswerView(APIView):
    def post(self, request, question_id):
        target_question = QnAQuestionModel.objects.get(id=question_id)
        request.data['is_selected'] = False
        request.data['user'] = request.user.id
        request.data['question'] = target_question.id
        answer_serializer = AnswerSerializer(data=request.data)
				if answer_serializer.is_valid():
            answer_serializer.save(**after_valid_datas)
            return Response({"message": "답변 작성 고맙거북"}, status=status.HTTP_200_OK)
        else:
            print(answer_serializer.errors)
            return Response({"message": "답변 작성 실패거북"}, status=status.HTTP_400_BAD_REQUEST)

views에서는 작동하는데 테스트코드는 작동하지 않는다?

  • view에서 작성한 함수 뷰가 POSTMAN에서 잘 통과하는 것을 확인한 뒤, 테스트코드를 작성했는데, 분명히 같은 코드를 통과하는데 작동이 되질 않는다.
  • 오류메시지는 QueryDict is Immutable 이라는 것만 계속 뱉을 뿐이다…

Immutable QueryDict 와 시리얼라이저

  • Immutable은 데이터를 변경할 수 없다는 것을 의미한다.
  • 원래의 리스트와 딕셔너리 자료형의 데이터는 Mutable 즉, 변경이 가능하지만 QueryDict는 변경할 수가 없다..
  • 뷰에서 사용한 request.data는 POSTMAN에서 테스트할 때는 dict 자료형이라고 타입을 출력하지만, 테스트코드는 어떤 과정을 거치는지 모두 알 수 없지만 QueryDict 자료형이라고 타입을 출력한다.
  • 따라서 request.data 에 원하는 데이터를 비집어 넣는 것은 불가능하다. 이말은 기존의 코드를 쓸 수 없다는 말이 된다…

시리얼라이저 검증과 save(), 모델 외래키(FK)의 SET_NULL 옵션

  • 데이터를 JSON으로 받고 JSON으로 내보내기 위해서는 DRF(Django Rest Framework)에서 시리얼라이저라는 것을 사용한다.
  • 시리얼라이저를 변수로 선언하면 반드시 is_valid() 함수를 통해서 반드시 데이터 검증을 거쳐야 한다. 모델에서 작성한 대로 형식은 맞는지, 제대로 들어왔는지 검증을 지나고 나서 데이터를 저장, 수정, 출력할 수 있게 된다.
  • 그런데 데이터를 중간에 바꿀 수 없는 QueryDict 형식이 중간에 가로막고 있기 때문에, 입력받은 데이터 이외의 정보는 따로 검증을 통과하고 저장할 수 밖에 없다.
  • FK 중에서 on_delete=CASCADE 라는 옵션이 있다. 이건 참조하는 키의 레코드가 삭제되면 지금 작성하려는 데이터도 자동으로 삭제하는 옵션인데, 이걸 하려면 데이터가 반드시 들어있어야 한다.
  • 헌데 테스트에 계속 실패하는 이유는 입력받은 데이터 이외에는 수정해줄 수가 없기 때문에, 검증에서 자꾸 실패하는 것이다. 필수로 받아야 하는 필드가 없으니까
  • 그래서 필수 필드를 일단 공란으로 비워두고 추후에 저장할 수 있도록 삭제 옵션을 변경해줘야 한다. 뭐로? SET_NULL
  • SET_NULL은 만약 참조하고 있는 외래키의 레코드가 사라지면 작성하고 있는 레코드의 참조키 값을 null로 남겨두는 방식이다. null을 허용하는 셈이다.
  • 따라서 SET_NULL로 on_delete 옵션을 변경하고 다시 코드를 진행하면, 데이터를 비워둔 상태에서 검증을 마치고 마지막에 데이터를 넣어 저장할 수 있게된다!
profile
하루종일 몽상가

0개의 댓글