405 error when custom-defined PATCH method is called for Django REST APIView
<p>I am making an API call in the test client:</p>

<pre><code>response2 = self.client.patch('/object/update/%d/' %
                                object_id, {'object_attribute':4})
</code></pre>

<p>The relevant serializer and view class for the object:</p>

<pre><code>class ObjectUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Object
        include=('object_attribte','another_attribute',)

class ObjectView(APIView):
    def patch(self, request, pk, format=None):
        obj = Object.objects.get(id=pk)
        data = request.data.copy()
        """do some stuff with the data here..."""
        serializer = ObjectUpdateSerializer(instance = obj, data=data,
                                            partial=True)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
            return Response(serializer.data,status.HTTP_200_OK)
</code></pre>

<p>I was able to work with the PUT method when I used that, but I wanted to have the API call methods be more in-line with what the methods actually mean (so PATCH would be a partial replacement). However, the response to the test client call above is this:</p>

<pre><code>{u'detail': u'Method "PATCH" not allowed.'}
</code></pre>

<p>Which is a 405 error (method not allowed). </p>

<p>I checked to see if there were any issues with Django 1.10, and I also got this output in the django shell:</p>

<pre><code>&gt;&gt;&gt; from django.views.generic import View
&gt;&gt;&gt; View.http_method_names
[u'get', u'post', u'put', u'patch', u'delete', u'head', u'options', u'trace']
</code></pre>

<p>It appears as if it isn't an issue with Django's settings, but something that I've set up. What could be the issue here?</p>

<p>I faced the same problem. It appeared that it's not allowed to use different views for the same route:</p>

<pre><code>urlpatterns = [
    # ...
    url('^sessions/?$', views.TokenDelete.as_view()), # Viewer has delete()
    url('^sessions/?$', views.TokenEdit.as_view()),   # Viewer has patch()
]
</code></pre>

<p>The correct way is:</p>

<pre><code>urlpatterns = [
    # ...
    url('^sessions/?$', views.Token.as_view()), # Viewer has both patch() and delete()
]
</code></pre>

python django django-rest-framework http-status-code-405