DRF put을 이용한 수정 구현과정에서 save메서드를 사용했을때 수정이 아닌 수정내용을 가진 새로운 인스턴스가 저장이 되는 문제 발생
def put(self, request, product_id):
product = get_object_or_404(Product, id=product_id)
serializer = ProductCreateSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
save메서드에 product를 전달해줘봤다.
save(product)
-> TypeError: save() takes 1 positional argument but 2 were given
에러가 뜬다. 어떤 매개변수를 받고 있는지 확인하기 위해 실제 위치를 타고 가봤다.
def save(self, **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가 존재할 경우 if문 실행
존재하지 않는경우 else문이 실행되고 있다.
지금 문제를 마주한 경우는 else문으로 빠져서 새로운 인스턴스를 생성하고 있는 상황이었다.
내가 원하는 동작은 update기능으로 if문이 실행이 돼야 한다. 요청값에 product_id를 전달해줬음에도 else문으로 빠졌다는 것은 update구현 코드에서 product전달 문제가 있다는 것 같았다.
다른 문제는 없는지 save메서드를 다시 쓰기 전에 원하는 기능인 update메서드로 진행을 해봤다.
필요한 값인 instance와 validated_data를 전달해줬다.
update(product, validated_data=request.data)
-> 원하는 기능 동작!
save메서드를 사용했을때 product가 제대로 전달이 되지 않아서 새로운 데이터로 인식이 된 상태였기 때문에 발생한 문제였다.
def put(self, request, product_id):
product = get_object_or_404(Product, id=product_id)
serializer = ProductCreateSerializer(product, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializer를 product에 대해 진행하도록 지정을 해주고 save메서드를 호출해서 해결했다.
그럼 처음 시도한 save(product)에서는 왜 오류가 났을까?
save메서드가 받는 매개변수는
(self, **kwargs)
로 save메서드를 호출할때 이미 serializer라는 self를 받아왔는데 product를 추가적으로 받았기 때문에 에러가 났었던 것이다.
때문에 serializer를 진행할때 product를 전달해주어 원하는 인스턴스에 save메서드를 적용할 수 있었다.