【DRF】PUT 메소드를 POST 메소드 대신 사용
Django REST Framework에서 PUT 메소드로 레코드 (인스턴스)를 만들고 싶다면
Django REST Framework(DRF)에 한하지 않고, REST API에서는 통상, HTTP 프로토콜의 POST
메소드로 인스턴스(=레코드)를 작성해 PUT
메소드로 갱신을 하지만, PUT
로 작성하는 것은 할 수 없는지 조사해 보았는데 방법이 있었으므로 비망록으로서 남겨 둔다.
일어난 문제와 하고 싶은 일
PUT
를 사용하여 레코드 업데이트 (예 : 사용자가 한 번 작성한 레코드의 데이터를 편집 한 경우)를 사용했지만 DB에 존재하지 않는 레코드를 PUT
로 보내려고하면 404
했다. 보통은 POST
로 레코드로 작성하려고 하고 있지만, PUT
에서도 레코드를 작성할 수 있도록 하고 싶다.
다시 한번, 설명한다고 상정하고 있는 거동은 다음과 같다.
[ 이렇게 했으면 좋겠다 ]
POST
로 레코드를 신규 작성해, PUT
인가 PATCH
(부분 갱신)로 레코드의 갱신 PUT
에서 업데이트하려고 시도한 레코드가 DB에 존재하지 않으면 404 오류없이 새로 생성됩니다.POST나 PUT, PATCH의 차이를 잘 모르는 경우는 PUT, POST 또는 PATCH?
해결책
공식 튜토리얼의 PUT as create 에 해결법이 실렸다.
Prior to version 3.0 the REST framework mixins treated PUT as either an update or a create operation, depending on if the object already existed or not.
Allowing PUT as create operations is problematic, as it necessarily exposes information about the existence or non-existence of objects. It's also not obvious that transparently allowing re-creating of previously deleted instances is necessarily a better default behavior tes simp.
Both styles "PUT as 404"and "PUT as create"can be valid in different circumstances, but from version 3.0 onwards we now use 404 behavior as the default, due to it being simpler and more obvious.
If you need to generic PUT-as-create behavior you may want to include something like this AllowPUTAsCreateMixin class as a mixin to your views.
요점은, 「DRF 버젼 3.0 이상에서는
PUT
로 존재하지 않는 레코드를 갱신하려고 하면 404
스테이터스가 되돌아오게 되어 있지만 와 같이 레코드를 신규 작성할 수 있게 된다」라고 하는 것 같다.상기 링크처의 스니펫과 같은 것이지만, 필요한 모듈의 임포트문이 빠져 있었기 때문에 더한 것을 실어 둔다. 이것을 임포트해 레코드 갱신에 사용하고 있는 View 클래스에 Mixin 하면
PUT
에서도 레코드 작성을 할 수 있게 된다. 프런트 엔드에서 조건 분기로 POST
메소드와 PUT
메소드를 구분하는 경우 등에 POST
의 메소드만으로 작성과 갱신의 양쪽 모두를 끝낼 수 있으므로, 코드가 간결하게 될 것 같다 put_as_create.py
from django.http import Http404
from rest_framework import status
from rest_framework.response import Response
from rest_framework.request import clone_request
class AllowPUTAsCreateMixin(object):
"""
The following mixin class may be used in order to support PUT-as-create
behavior for incoming requests.
"""
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object_or_none()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
if instance is None:
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
lookup_value = self.kwargs[lookup_url_kwarg]
extra_kwargs = {self.lookup_field: lookup_value}
serializer.save(**extra_kwargs)
return Response(serializer.data, status=status.HTTP_201_CREATED)
serializer.save()
return Response(serializer.data)
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
def get_object_or_none(self):
try:
return self.get_object()
except Http404:
if self.request.method == 'PUT':
# For PUT-as-create operation, we need to ensure that we have
# relevant permissions, as if this was a POST request. This
# will either raise a PermissionDenied exception, or simply
# return None.
self.check_permissions(clone_request(self.request, 'POST'))
else:
# PATCH requests where the object does not exist should still
# return a 404 response.
raise
Reference
이 문제에 관하여(【DRF】PUT 메소드를 POST 메소드 대신 사용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/_masa_u/items/a7a67a9744aa58ec3eef텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)