mirror of
https://github.com/django/django.git
synced 2025-06-05 03:29:12 +00:00
Fixed #15637 -- Added a require_safe decorator for views to accept GET or HEAD. Thanks, aaugustin and Julien.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16115 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
013ce8aca2
commit
086ab44336
@ -48,6 +48,9 @@ require_GET.__doc__ = "Decorator to require that a view only accept the GET meth
|
|||||||
require_POST = require_http_methods(["POST"])
|
require_POST = require_http_methods(["POST"])
|
||||||
require_POST.__doc__ = "Decorator to require that a view only accept the POST method."
|
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):
|
def condition(etag_func=None, last_modified_func=None):
|
||||||
"""
|
"""
|
||||||
Decorator to support conditional retrieval (or change) for a view
|
Decorator to support conditional retrieval (or change) for a view
|
||||||
|
@ -10,31 +10,47 @@ various HTTP features.
|
|||||||
Allowed HTTP methods
|
Allowed HTTP methods
|
||||||
====================
|
====================
|
||||||
|
|
||||||
The following decorators in :mod:`django.views.decorators.http` can be used to
|
The decorators in :mod:`django.views.decorators.http` can be used to restrict
|
||||||
restrict access to views based on the request method.
|
access to views based on the request method.
|
||||||
|
|
||||||
.. function:: require_http_methods(request_method_list)
|
.. function:: require_http_methods(request_method_list)
|
||||||
|
|
||||||
This decorator is used to ensure that a view only accepts particular request
|
Decorator to require that a view only accept particular request
|
||||||
methods. Usage::
|
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"])
|
@require_http_methods(["GET", "POST"])
|
||||||
def my_view(request):
|
def my_view(request):
|
||||||
# I can assume now that only GET or POST requests make it this far
|
# I can assume now that only GET or POST requests make it this far
|
||||||
# ...
|
# ...
|
||||||
pass
|
pass
|
||||||
|
|
||||||
Note that request methods should be in uppercase.
|
Note that request methods should be in uppercase.
|
||||||
|
|
||||||
.. function:: require_GET()
|
.. 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()
|
.. 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
|
Conditional view processing
|
||||||
===========================
|
===========================
|
||||||
@ -48,9 +64,9 @@ control caching behavior on particular views.
|
|||||||
|
|
||||||
.. function:: last_modified(last_modified_func)
|
.. function:: last_modified(last_modified_func)
|
||||||
|
|
||||||
These decorators can be used to generate ``ETag`` and ``Last-Modified``
|
These decorators can be used to generate ``ETag`` and ``Last-Modified``
|
||||||
headers; see
|
headers; see
|
||||||
:doc:`conditional view processing </topics/conditional-view-processing>`.
|
:doc:`conditional view processing </topics/conditional-view-processing>`.
|
||||||
|
|
||||||
.. module:: django.views.decorators.gzip
|
.. module:: django.views.decorators.gzip
|
||||||
|
|
||||||
@ -62,9 +78,9 @@ compression on a per-view basis.
|
|||||||
|
|
||||||
.. function:: gzip_page()
|
.. function:: gzip_page()
|
||||||
|
|
||||||
This decorator compresses content if the browser allows gzip compression.
|
This decorator compresses content if the browser allows gzip compression.
|
||||||
It sets the ``Vary`` header accordingly, so that caches will base their
|
It sets the ``Vary`` header accordingly, so that caches will base their
|
||||||
storage on the ``Accept-Encoding`` header.
|
storage on the ``Accept-Encoding`` header.
|
||||||
|
|
||||||
.. module:: django.views.decorators.vary
|
.. module:: django.views.decorators.vary
|
||||||
|
|
||||||
@ -78,7 +94,7 @@ caching based on specific request headers.
|
|||||||
|
|
||||||
.. function:: vary_on_headers(*headers)
|
.. function:: vary_on_headers(*headers)
|
||||||
|
|
||||||
The ``Vary`` header defines which request headers a cache mechanism should take
|
The ``Vary`` header defines which request headers a cache mechanism should take
|
||||||
into account when building its cache key.
|
into account when building its cache key.
|
||||||
|
|
||||||
See :ref:`using vary headers <using-vary-headers>`.
|
See :ref:`using vary headers <using-vary-headers>`.
|
||||||
|
@ -2,11 +2,11 @@ from functools import wraps
|
|||||||
|
|
||||||
from django.contrib.auth.decorators import login_required, permission_required, user_passes_test
|
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.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.decorators import method_decorator
|
||||||
from django.utils.functional import allow_lazy, lazy, memoize
|
from django.utils.functional import allow_lazy, lazy, memoize
|
||||||
from django.utils.unittest import TestCase
|
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.vary import vary_on_headers, vary_on_cookie
|
||||||
from django.views.decorators.cache import cache_page, never_cache, cache_control
|
from django.views.decorators.cache import cache_page, never_cache, cache_control
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ fully_decorated.anything = "Expected __dict__"
|
|||||||
fully_decorated = require_http_methods(["GET"])(fully_decorated)
|
fully_decorated = require_http_methods(["GET"])(fully_decorated)
|
||||||
fully_decorated = require_GET(fully_decorated)
|
fully_decorated = require_GET(fully_decorated)
|
||||||
fully_decorated = require_POST(fully_decorated)
|
fully_decorated = require_POST(fully_decorated)
|
||||||
|
fully_decorated = require_safe(fully_decorated)
|
||||||
|
|
||||||
# django.views.decorators.vary
|
# django.views.decorators.vary
|
||||||
fully_decorated = vary_on_headers('Accept-language')(fully_decorated)
|
fully_decorated = vary_on_headers('Accept-language')(fully_decorated)
|
||||||
@ -111,6 +112,27 @@ class DecoratorsTest(TestCase):
|
|||||||
my_view_cached4 = cache_page()(my_view)
|
my_view_cached4 = cache_page()(my_view)
|
||||||
self.assertEqual(my_view_cached4(HttpRequest()), "response")
|
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.
|
# 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.
|
# We will get type arguments if there is a mismatch in the number of arguments.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user