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 옵션을 변경하고 다시 코드를 진행하면, 데이터를 비워둔 상태에서 검증을 마치고 마지막에 데이터를 넣어 저장할 수 있게된다!