diff --git a/rest_framework/generics.py b/rest_framework/generics.py index 88438e8c4..dc45bda01 100644 --- a/rest_framework/generics.py +++ b/rest_framework/generics.py @@ -229,8 +229,9 @@ class UpdateAPIView(mixins.UpdateModelMixin, def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) - def patch(self, request, *args, **kwargs): - return self.partial_update(request, *args, **kwargs) + if api_settings.SUPPORT_PATCH: + def patch(self, request, *args, **kwargs): + return self.partial_update(request, *args, **kwargs) class ListCreateAPIView(mixins.ListModelMixin, @@ -258,8 +259,9 @@ class RetrieveUpdateAPIView(mixins.RetrieveModelMixin, def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) - def patch(self, request, *args, **kwargs): - return self.partial_update(request, *args, **kwargs) + if api_settings.SUPPORT_PATCH: + def patch(self, request, *args, **kwargs): + return self.partial_update(request, *args, **kwargs) class RetrieveDestroyAPIView(mixins.RetrieveModelMixin, @@ -288,8 +290,9 @@ class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin, def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) - def patch(self, request, *args, **kwargs): - return self.partial_update(request, *args, **kwargs) + if api_settings.SUPPORT_PATCH: + def patch(self, request, *args, **kwargs): + return self.partial_update(request, *args, **kwargs) def delete(self, request, *args, **kwargs): return self.destroy(request, *args, **kwargs) diff --git a/rest_framework/views.py b/rest_framework/views.py index faa197e1e..a709c2f6b 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -129,12 +129,7 @@ class APIView(View): """ Wrap Django's private `_allowed_methods` interface in a public property. """ - allowed_methods = self._allowed_methods() - - if not api_settings.SUPPORT_PATCH and 'PATCH' in allowed_methods: - allowed_methods.remove('PATCH') - - return allowed_methods + return self._allowed_methods() @property def default_response_headers(self): @@ -456,7 +451,7 @@ class APIView(View): self.initial(request, *args, **kwargs) # Get the appropriate handler method - if request.method in self.allowed_methods: + if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: diff --git a/tests/test_generics.py b/tests/test_generics.py index d98c86dea..083f95f60 100644 --- a/tests/test_generics.py +++ b/tests/test_generics.py @@ -4,10 +4,11 @@ import django from django.db import models from django.shortcuts import get_object_or_404 from django.test import TestCase +from django.test.utils import override_settings from django.utils import six +from django.utils.six.moves import reload_module from rest_framework import generics, renderers, serializers, status -from rest_framework.settings import api_settings from rest_framework.test import APIRequestFactory from tests.models import ( BasicModel, ForeignKeySource, ForeignKeyTarget, RESTFrameworkModel @@ -214,19 +215,6 @@ class TestInstanceView(TestCase): updated = self.objects.get(id=1) self.assertEqual(updated.text, 'foobar') - def test_patch_instance_view_support_patch(self): - """ - PATCH requests with SUPPORT_PATCH=False should return 405 - """ - data = {'text': 'foobar'} - request = factory.patch('/1', data, format='json') - - api_settings.SUPPORT_PATCH = False - response = self.view(request, pk=1).render() - api_settings.SUPPORT_PATCH = True - - self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) - def test_delete_instance_view(self): """ DELETE requests to RetrieveUpdateDestroyAPIView should delete an object. @@ -521,3 +509,22 @@ class TestFilterBackendAppliedToViews(TestCase): response = view(request).render() self.assertContains(response, 'field_b') self.assertNotContains(response, 'field_a') + + +class TestSupportPatchSetting(TestCase): + def test_patch_instance_view_support_patch(self): + """ + PATCH requests should fail when SUPPORT_PATCH is set to False. + """ + with override_settings(REST_FRAMEWORK={'SUPPORT_PATCH': False}): + reload_module(generics) + data = {'text': 'foobar'} + request = factory.patch('/1', data, format='json') + + class InstanceView(generics.UpdateAPIView): + queryset = BasicModel.objects.all() + serializer_class = BasicSerializer + + view = InstanceView.as_view() + response = view(request, pk=1).render() + self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)