In DRF, I have a simple ViewSet like this one:
class MyViewSet(viewsets.ViewSet):
def update(self, request):
# do things...
return Response(status=status.HTTP_200_OK)
When I try a PUT request, I get an error like method PUT not allowed. If I use def put(self, request):
all things work fine. Accordingly to the docs I should use def update():
not def put():
, why does it happen?
Had a similar "Method PUT not allowed" issue with this code, because 'id' was missing in the request:
Turned out that i have missed 'id' in the serializer fields, so PUT request was NOT able to provide an id for the record. The fixed version of the serializer is below:
This answer is right, Django REST framework: method PUT not allowed in ViewSet with def update(), PUT is not allowed, because DRF expects the instance id to be in the URL. That being said, using this mixin in your ViewSet is probably the best way to fix it (from https://gist.github.com/tomchristie/a2ace4577eff2c603b1b copy pasted below)
This is because the
APIView
has no handler defined for.put()
method so the incoming request could not be mapped to a handler method on the view, thereby raising an exception.(Note:
viewsets.ViewSet
inherit fromViewSetMixin
andAPIView
)The
dispatch()
method in theAPIView
checks if a method handler is defined for the requestmethod
.If thedispatch()
method finds a handler for the request method, it returns the appropriate response. Otherwise, it raises an exceptionMethodNotAllowed
.As per the source code of
dispatch()
method in theAPIView
class:Since
.put()
method handler is not defined in your view, DRF calls the fallback handler.http_method_not_allowed
. This raises anMethodNotAllowed
exception.The source code for
.http_method_not_allowed()
is:Why it worked when you defined
.put()
in your view?When you defined
def put(self, request):
in your view, DRF could map the incoming request method to a handler method on the view. This led to appropriate response being returned without an exception being raised.Sometimes it is different for POST and PUT, because PUT uses id in URL In this case yoy'll get this error: "PUT is not Allowed".
Example:
/api/users/
/api/users/1/
Hope it'll save a lot of time for somebody