Fixed #17449 -- Added OPTIONS to generic views.
Thanks estebistec for the report and patch.
This commit is contained in:
parent
009e237cf0
commit
c4996df16c
|
@ -79,14 +79,22 @@ class View(object):
|
||||||
return handler(request, *args, **kwargs)
|
return handler(request, *args, **kwargs)
|
||||||
|
|
||||||
def http_method_not_allowed(self, request, *args, **kwargs):
|
def http_method_not_allowed(self, request, *args, **kwargs):
|
||||||
allowed_methods = [m for m in self.http_method_names if hasattr(self, m)]
|
|
||||||
logger.warning('Method Not Allowed (%s): %s', request.method, request.path,
|
logger.warning('Method Not Allowed (%s): %s', request.method, request.path,
|
||||||
extra={
|
extra={
|
||||||
'status_code': 405,
|
'status_code': 405,
|
||||||
'request': self.request
|
'request': self.request
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return http.HttpResponseNotAllowed(allowed_methods)
|
return http.HttpResponseNotAllowed(self._allowed_methods())
|
||||||
|
|
||||||
|
def options(self, request, *args, **kwargs):
|
||||||
|
response = http.HttpResponse()
|
||||||
|
response['Allow'] = ', '.join(self._allowed_methods())
|
||||||
|
response['Content-Length'] = 0
|
||||||
|
return response
|
||||||
|
|
||||||
|
def _allowed_methods(self):
|
||||||
|
return [m.upper() for m in self.http_method_names if hasattr(self, m)]
|
||||||
|
|
||||||
|
|
||||||
class TemplateResponseMixin(object):
|
class TemplateResponseMixin(object):
|
||||||
|
|
|
@ -173,6 +173,58 @@ class ViewTest(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
self.assertTrue(DecoratedDispatchView.as_view().is_decorated)
|
self.assertTrue(DecoratedDispatchView.as_view().is_decorated)
|
||||||
|
|
||||||
|
def test_head_no_get(self):
|
||||||
|
"""
|
||||||
|
Test that a view class with no get responds to a HEAD request with HTTP
|
||||||
|
405.
|
||||||
|
"""
|
||||||
|
request = self.rf.head('/')
|
||||||
|
view = PostOnlyView.as_view()
|
||||||
|
self.assertEqual(405, view(request).status_code)
|
||||||
|
|
||||||
|
def test_options(self):
|
||||||
|
"""
|
||||||
|
Test that views respond to HTTP OPTIONS requests with an Allow header
|
||||||
|
appropriate for the methods implemented by the view class.
|
||||||
|
"""
|
||||||
|
request = self.rf.options('/')
|
||||||
|
view = SimpleView.as_view()
|
||||||
|
response = view(request)
|
||||||
|
self.assertEqual(200, response.status_code)
|
||||||
|
self.assertTrue(response['Allow'])
|
||||||
|
|
||||||
|
def test_options_for_get_view(self):
|
||||||
|
"""
|
||||||
|
Test that a view implementing GET allows GET and HEAD.
|
||||||
|
"""
|
||||||
|
request = self.rf.options('/')
|
||||||
|
view = SimpleView.as_view()
|
||||||
|
response = view(request)
|
||||||
|
self._assert_allows(response, 'GET', 'HEAD')
|
||||||
|
|
||||||
|
def test_options_for_get_and_post_view(self):
|
||||||
|
"""
|
||||||
|
Test that a view implementing GET and POST allows GET, HEAD, and POST.
|
||||||
|
"""
|
||||||
|
request = self.rf.options('/')
|
||||||
|
view = SimplePostView.as_view()
|
||||||
|
response = view(request)
|
||||||
|
self._assert_allows(response, 'GET', 'HEAD', 'POST')
|
||||||
|
|
||||||
|
def test_options_for_post_view(self):
|
||||||
|
"""
|
||||||
|
Test that a view implementing POST allows POST.
|
||||||
|
"""
|
||||||
|
request = self.rf.options('/')
|
||||||
|
view = PostOnlyView.as_view()
|
||||||
|
response = view(request)
|
||||||
|
self._assert_allows(response, 'POST')
|
||||||
|
|
||||||
|
def _assert_allows(self, response, *expected_methods):
|
||||||
|
"Assert allowed HTTP methods reported in the Allow response header"
|
||||||
|
response_allows = set(response['Allow'].split(', '))
|
||||||
|
self.assertEqual(set(expected_methods + ('OPTIONS',)), response_allows)
|
||||||
|
|
||||||
|
|
||||||
class TemplateViewTest(TestCase):
|
class TemplateViewTest(TestCase):
|
||||||
urls = 'regressiontests.generic_views.urls'
|
urls = 'regressiontests.generic_views.urls'
|
||||||
|
|
Loading…
Reference in New Issue