Ticket #17449: ticket-17449-default-options.patch

File ticket-17449-default-options.patch, 4.8 KB (added by Steven Cummings, 13 years ago)

Patch adjusted to only implement default OPTIONS

  • docs/ref/request-response.txt

     
    748748    The constructor doesn't take any arguments. Use this to designate that a
    749749    page hasn't been modified since the user's last request (status code 304).
    750750
     751.. class:: HttpResponseOptions
     752
     753    Like :class:`HttpResponse`, but uses a 200 status code and provides
     754    an ``Allow`` response header. Takes a single, required argument: a list
     755    of permitted methods (e.g., ``['GET', 'POST']``) used to populate
     756    the ``Allow`` header.
     757
    751758.. class:: HttpResponseBadRequest
    752759
    753760    Acts just like :class:`HttpResponse` but uses a 400 status code.
  • tests/regressiontests/generic_views/base.py

     
    170170        """
    171171        self.assertTrue(DecoratedDispatchView.as_view().is_decorated)
    172172
     173    def test_head_no_get(self):
     174        """
     175        Test that a view class with no get responds to a HEAD request with HTTP
     176        405.
     177        """
     178        request = self.rf.head('/')
     179        view = PostOnlyView.as_view()
     180        self.assertEqual(405, view(request).status_code)
    173181
     182    def test_options(self):
     183        """
     184        Test that views respond to HTTP OPTIONS requests with an Allow header
     185        appropriate for the methods implemented by the view class.
     186        """
     187        request = self.rf.options('/')
     188        view = SimpleView.as_view()
     189        response = view(request)
     190        self.assertEqual(200, response.status_code)
     191        self.assertTrue(response['Allow'])
     192
     193    def test_options_for_get_view(self):
     194        """
     195        Test that a view implementing GET allows GET and HEAD.
     196        """
     197        request = self.rf.options('/')
     198        view = SimpleView.as_view()
     199        response = view(request)
     200        self._assert_allows(response, 'GET', 'HEAD')
     201
     202    def test_options_for_get_and_post_view(self):
     203        """
     204        Test that a view implementing GET and POST allows GET, HEAD, and POST.
     205        """
     206        request = self.rf.options('/')
     207        view = SimplePostView.as_view()
     208        response = view(request)
     209        self._assert_allows(response, 'GET', 'HEAD', 'POST')
     210
     211    def test_options_for_post_view(self):
     212        """
     213        Test that a view implementing POST allows POST.
     214        """
     215        request = self.rf.options('/')
     216        view = PostOnlyView.as_view()
     217        response = view(request)
     218        self._assert_allows(response, 'POST')
     219
     220    def _assert_allows(self, response, *expected_methods):
     221        "Assert allowed HTTP methods reported in the Allow response header"
     222        response_allows = set(response['Allow'].split(', '))
     223        self.assertEqual(set(expected_methods + ('OPTIONS',)), response_allows)
     224
     225
    174226class TemplateViewTest(TestCase):
    175227    urls = 'regressiontests.generic_views.urls'
    176228
  • django/http/__init__.py

     
    726726            raise Exception("This %s instance cannot tell its position" % self.__class__)
    727727        return sum([len(str(chunk)) for chunk in self._container])
    728728
     729class HttpResponseOptions(HttpResponse):
     730    status_code = 200
     731
     732    def __init__(self, permitted_methods):
     733        super(HttpResponseOptions, self).__init__()
     734        self['Allow'] = ', '.join(permitted_methods)
     735        self['Content-Length'] = '0'
     736
    729737class HttpResponseRedirect(HttpResponse):
    730738    status_code = 302
    731739
  • django/views/generic/base.py

     
    6969        return handler(request, *args, **kwargs)
    7070
    7171    def http_method_not_allowed(self, request, *args, **kwargs):
    72         allowed_methods = [m for m in self.http_method_names if hasattr(self, m)]
    7372        logger.warning('Method Not Allowed (%s): %s', request.method, request.path,
    7473            extra={
    7574                'status_code': 405,
    7675                'request': self.request
    7776            }
    7877        )
    79         return http.HttpResponseNotAllowed(allowed_methods)
     78        return http.HttpResponseNotAllowed(self._allowed_methods())
    8079
     80    def options(self, request, *args, **kwargs):
     81        return http.HttpResponseOptions(self._allowed_methods())
    8182
     83    def _allowed_methods(self):
     84        return [m.upper() for m in self.http_method_names if hasattr(self, m)]
     85
     86
    8287class TemplateResponseMixin(object):
    8388    """
    8489    A mixin that can be used to render a template.
Back to Top