diff --git a/django/views/decorators/http.py b/django/views/decorators/http.py
index dc90cc3..054dc57 100644
a
|
b
|
require_GET.__doc__ = "Decorator to require that a view only accept the GET meth
|
48 | 48 | require_POST = require_http_methods(["POST"]) |
49 | 49 | require_POST.__doc__ = "Decorator to require that a view only accept the POST method." |
50 | 50 | |
| 51 | require_safe = require_http_methods(["GET", "HEAD"]) |
| 52 | require_safe.__doc__ = "Decorator to require that a view only accept safe methods: GET and HEAD." |
| 53 | |
51 | 54 | def condition(etag_func=None, last_modified_func=None): |
52 | 55 | """ |
53 | 56 | Decorator to support conditional retrieval (or change) for a view |
diff --git a/docs/topics/http/decorators.txt b/docs/topics/http/decorators.txt
index 09ffecb..d7d2803 100644
a
|
b
|
various HTTP features.
|
10 | 10 | Allowed HTTP methods |
11 | 11 | ==================== |
12 | 12 | |
13 | | The following decorators in :mod:`django.views.decorators.http` can be used to |
14 | | restrict access to views based on the request method. |
| 13 | The decorators in :mod:`django.views.decorators.http` can be used to restrict |
| 14 | access to views based on the request method. |
15 | 15 | |
16 | 16 | .. function:: require_http_methods(request_method_list) |
17 | 17 | |
18 | | This decorator is used to ensure that a view only accepts particular request |
19 | | methods. Usage:: |
20 | | |
21 | | from django.views.decorators.http import require_http_methods |
| 18 | Decorator to require that a view only accept particular request |
| 19 | methods. Usage:: |
| 20 | |
| 21 | from django.views.decorators.http import require_http_methods |
| 22 | |
| 23 | @require_http_methods(["GET", "POST"]) |
| 24 | def my_view(request): |
| 25 | # I can assume now that only GET or POST requests make it this far |
| 26 | # ... |
| 27 | pass |
| 28 | |
| 29 | Note that request methods should be in uppercase. |
| 30 | |
| 31 | .. function:: require_GET() |
22 | 32 | |
23 | | @require_http_methods(["GET", "POST"]) |
24 | | def my_view(request): |
25 | | # I can assume now that only GET or POST requests make it this far |
26 | | # ... |
27 | | pass |
| 33 | Decorator to require that a view only accept the GET method. |
28 | 34 | |
29 | | Note that request methods should be in uppercase. |
| 35 | .. function:: require_POST() |
30 | 36 | |
31 | | .. function:: require_GET() |
| 37 | Decorator to require that a view only accept the POST method. |
32 | 38 | |
33 | | Decorator to require that a view only accept the GET method. |
| 39 | .. function:: require_safe() |
34 | 40 | |
35 | | .. function:: require_POST() |
| 41 | .. versionadded:: Development version |
36 | 42 | |
37 | | Decorator to require that a view only accept the POST method. |
| 43 | Decorator to require that a view only accept the GET and HEAD methods. |
| 44 | These methods are commonly considered "safe" because they should not have |
| 45 | the significance of taking an action other than retrieving the requested |
| 46 | resource. |
| 47 | |
| 48 | .. note:: |
| 49 | Django will automatically strip the content of responses to HEAD |
| 50 | requests while leaving the headers unchanged, so you may handle HEAD |
| 51 | requests exactly like GET requests in your views. Since some software, |
| 52 | such as link checkers, rely on HEAD requests, you might prefer |
| 53 | using ``require_safe`` instead of ``require_GET``. |
38 | 54 | |
39 | 55 | Conditional view processing |
40 | 56 | =========================== |
diff --git a/tests/regressiontests/decorators/tests.py b/tests/regressiontests/decorators/tests.py
index dac4029..52a1ecd 100644
a
|
b
|
from functools import wraps
|
2 | 2 | |
3 | 3 | from django.contrib.auth.decorators import login_required, permission_required, user_passes_test |
4 | 4 | from django.contrib.admin.views.decorators import staff_member_required |
5 | | from django.http import HttpResponse, HttpRequest |
| 5 | from django.http import HttpResponse, HttpRequest, HttpResponseNotAllowed |
6 | 6 | from django.utils.decorators import method_decorator |
7 | 7 | from django.utils.functional import allow_lazy, lazy, memoize |
8 | 8 | from django.utils.unittest import TestCase |
9 | | from django.views.decorators.http import require_http_methods, require_GET, require_POST |
| 9 | from django.views.decorators.http import require_http_methods, require_GET, require_POST, require_safe |
10 | 10 | from django.views.decorators.vary import vary_on_headers, vary_on_cookie |
11 | 11 | from django.views.decorators.cache import cache_page, never_cache, cache_control |
12 | 12 | |
… |
… |
fully_decorated.anything = "Expected __dict__"
|
20 | 20 | fully_decorated = require_http_methods(["GET"])(fully_decorated) |
21 | 21 | fully_decorated = require_GET(fully_decorated) |
22 | 22 | fully_decorated = require_POST(fully_decorated) |
| 23 | fully_decorated = require_safe(fully_decorated) |
23 | 24 | |
24 | 25 | # django.views.decorators.vary |
25 | 26 | fully_decorated = vary_on_headers('Accept-language')(fully_decorated) |
… |
… |
class DecoratorsTest(TestCase):
|
111 | 112 | my_view_cached4 = cache_page()(my_view) |
112 | 113 | self.assertEqual(my_view_cached4(HttpRequest()), "response") |
113 | 114 | |
| 115 | def test_require_safe_accepts_only_safe_methods(self): |
| 116 | """ |
| 117 | Test for the require_safe decorator. |
| 118 | A view returns either a response or an exception. |
| 119 | Refs #15637. |
| 120 | """ |
| 121 | def my_view(request): |
| 122 | return HttpResponse("OK") |
| 123 | my_safe_view = require_safe(my_view) |
| 124 | request = HttpRequest() |
| 125 | request.method = 'GET' |
| 126 | self.assertTrue(isinstance(my_safe_view(request), HttpResponse)) |
| 127 | request.method = 'HEAD' |
| 128 | self.assertTrue(isinstance(my_safe_view(request), HttpResponse)) |
| 129 | request.method = 'POST' |
| 130 | self.assertTrue(isinstance(my_safe_view(request), HttpResponseNotAllowed)) |
| 131 | request.method = 'PUT' |
| 132 | self.assertTrue(isinstance(my_safe_view(request), HttpResponseNotAllowed)) |
| 133 | request.method = 'DELETE' |
| 134 | self.assertTrue(isinstance(my_safe_view(request), HttpResponseNotAllowed)) |
| 135 | |
114 | 136 | |
115 | 137 | # For testing method_decorator, a decorator that assumes a single argument. |
116 | 138 | # We will get type arguments if there is a mismatch in the number of arguments. |