Author: jezdez
Date: 2011-04-28 06:04:16 -0700 (Thu, 28 Apr 2011)
New Revision: 16115

Modified:
   django/trunk/django/views/decorators/http.py
   django/trunk/docs/topics/http/decorators.txt
   django/trunk/tests/regressiontests/decorators/tests.py
Log:
Fixed #15637 -- Added a require_safe decorator for views to accept GET or HEAD. 
Thanks, aaugustin and Julien.

Modified: django/trunk/django/views/decorators/http.py
===================================================================
--- django/trunk/django/views/decorators/http.py        2011-04-28 01:47:21 UTC 
(rev 16114)
+++ django/trunk/django/views/decorators/http.py        2011-04-28 13:04:16 UTC 
(rev 16115)
@@ -48,6 +48,9 @@
 require_POST = require_http_methods(["POST"])
 require_POST.__doc__ = "Decorator to require that a view only accept the POST 
method."
 
+require_safe = require_http_methods(["GET", "HEAD"])
+require_safe.__doc__ = "Decorator to require that a view only accept safe 
methods: GET and HEAD."
+
 def condition(etag_func=None, last_modified_func=None):
     """
     Decorator to support conditional retrieval (or change) for a view

Modified: django/trunk/docs/topics/http/decorators.txt
===================================================================
--- django/trunk/docs/topics/http/decorators.txt        2011-04-28 01:47:21 UTC 
(rev 16114)
+++ django/trunk/docs/topics/http/decorators.txt        2011-04-28 13:04:16 UTC 
(rev 16115)
@@ -10,32 +10,48 @@
 Allowed HTTP methods
 ====================
 
-The following decorators in :mod:`django.views.decorators.http` can be used to
-restrict access to views based on the request method.
+The decorators in :mod:`django.views.decorators.http` can be used to restrict
+access to views based on the request method.
 
 .. function:: require_http_methods(request_method_list)
 
-This decorator is used to ensure that a view only accepts particular request
-methods. Usage::
+    Decorator to require that a view only accept particular request
+    methods. Usage::
 
-    from django.views.decorators.http import require_http_methods
+        from django.views.decorators.http import require_http_methods
 
-    @require_http_methods(["GET", "POST"])
-    def my_view(request):
-        # I can assume now that only GET or POST requests make it this far
-        # ...
-        pass
+        @require_http_methods(["GET", "POST"])
+        def my_view(request):
+            # I can assume now that only GET or POST requests make it this far
+            # ...
+            pass
 
-Note that request methods should be in uppercase.
+    Note that request methods should be in uppercase.
 
 .. function:: require_GET()
 
-Decorator to require that a view only accept the GET method.
+    Decorator to require that a view only accept the GET method.
 
 .. function:: require_POST()
 
-Decorator to require that a view only accept the POST method.
+    Decorator to require that a view only accept the POST method.
 
+.. function:: require_safe()
+
+    .. versionadded:: 1.4
+
+    Decorator to require that a view only accept the GET and HEAD methods.
+    These methods are commonly considered "safe" because they should not have
+    the significance of taking an action other than retrieving the requested
+    resource.
+
+    .. note::
+        Django will automatically strip the content of responses to HEAD
+        requests while leaving the headers unchanged, so you may handle HEAD
+        requests exactly like GET requests in your views. Since some software,
+        such as link checkers, rely on HEAD requests, you might prefer
+        using ``require_safe`` instead of ``require_GET``.
+
 Conditional view processing
 ===========================
 
@@ -48,9 +64,9 @@
 
 .. function:: last_modified(last_modified_func)
 
-These decorators can be used to generate ``ETag`` and ``Last-Modified``
-headers; see
-:doc:`conditional view processing </topics/conditional-view-processing>`.
+    These decorators can be used to generate ``ETag`` and ``Last-Modified``
+    headers; see
+    :doc:`conditional view processing </topics/conditional-view-processing>`.
 
 .. module:: django.views.decorators.gzip
 
@@ -62,9 +78,9 @@
 
 .. function:: gzip_page()
 
-This decorator compresses content if the browser allows gzip compression.
-It sets the ``Vary`` header accordingly, so that caches will base their
-storage on the ``Accept-Encoding`` header.
+    This decorator compresses content if the browser allows gzip compression.
+    It sets the ``Vary`` header accordingly, so that caches will base their
+    storage on the ``Accept-Encoding`` header.
 
 .. module:: django.views.decorators.vary
 
@@ -78,7 +94,7 @@
 
 .. function:: vary_on_headers(*headers)
 
-The ``Vary`` header defines which request headers a cache mechanism should take
-into account when building its cache key.
+    The ``Vary`` header defines which request headers a cache mechanism should 
take
+    into account when building its cache key.
 
-See :ref:`using vary headers <using-vary-headers>`.
+    See :ref:`using vary headers <using-vary-headers>`.

Modified: django/trunk/tests/regressiontests/decorators/tests.py
===================================================================
--- django/trunk/tests/regressiontests/decorators/tests.py      2011-04-28 
01:47:21 UTC (rev 16114)
+++ django/trunk/tests/regressiontests/decorators/tests.py      2011-04-28 
13:04:16 UTC (rev 16115)
@@ -2,11 +2,11 @@
 
 from django.contrib.auth.decorators import login_required, 
permission_required, user_passes_test
 from django.contrib.admin.views.decorators import staff_member_required
-from django.http import HttpResponse, HttpRequest
+from django.http import HttpResponse, HttpRequest, HttpResponseNotAllowed
 from django.utils.decorators import method_decorator
 from django.utils.functional import allow_lazy, lazy, memoize
 from django.utils.unittest import TestCase
-from django.views.decorators.http import require_http_methods, require_GET, 
require_POST
+from django.views.decorators.http import require_http_methods, require_GET, 
require_POST, require_safe
 from django.views.decorators.vary import vary_on_headers, vary_on_cookie
 from django.views.decorators.cache import cache_page, never_cache, 
cache_control
 
@@ -20,6 +20,7 @@
 fully_decorated = require_http_methods(["GET"])(fully_decorated)
 fully_decorated = require_GET(fully_decorated)
 fully_decorated = require_POST(fully_decorated)
+fully_decorated = require_safe(fully_decorated)
 
 # django.views.decorators.vary
 fully_decorated = vary_on_headers('Accept-language')(fully_decorated)
@@ -111,7 +112,28 @@
         my_view_cached4 = cache_page()(my_view)
         self.assertEqual(my_view_cached4(HttpRequest()), "response")
 
+    def test_require_safe_accepts_only_safe_methods(self):
+        """
+        Test for the require_safe decorator.
+        A view returns either a response or an exception.
+        Refs #15637.
+        """
+        def my_view(request):
+            return HttpResponse("OK")
+        my_safe_view = require_safe(my_view)
+        request = HttpRequest()
+        request.method = 'GET'
+        self.assertTrue(isinstance(my_safe_view(request), HttpResponse))
+        request.method = 'HEAD'
+        self.assertTrue(isinstance(my_safe_view(request), HttpResponse))
+        request.method = 'POST'
+        self.assertTrue(isinstance(my_safe_view(request), 
HttpResponseNotAllowed))
+        request.method = 'PUT'
+        self.assertTrue(isinstance(my_safe_view(request), 
HttpResponseNotAllowed))
+        request.method = 'DELETE'
+        self.assertTrue(isinstance(my_safe_view(request), 
HttpResponseNotAllowed))
 
+
 # For testing method_decorator, a decorator that assumes a single argument.
 # We will get type arguments if there is a mismatch in the number of arguments.
 def simple_dec(func):

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to