mirror of https://github.com/django/django.git
Refs #31949 -- Made @no_append_slash decorator to work with async functions.
This commit is contained in:
parent
e5c844d6f2
commit
23abec9192
|
@ -1,5 +1,7 @@
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
from asgiref.sync import iscoroutinefunction
|
||||||
|
|
||||||
|
|
||||||
def no_append_slash(view_func):
|
def no_append_slash(view_func):
|
||||||
"""
|
"""
|
||||||
|
@ -9,9 +11,17 @@ def no_append_slash(view_func):
|
||||||
|
|
||||||
# view_func.should_append_slash = False would also work, but decorators are
|
# view_func.should_append_slash = False would also work, but decorators are
|
||||||
# nicer if they don't have side effects, so return a new function.
|
# nicer if they don't have side effects, so return a new function.
|
||||||
@wraps(view_func)
|
|
||||||
def wrapper_view(*args, **kwargs):
|
|
||||||
return view_func(*args, **kwargs)
|
|
||||||
|
|
||||||
wrapper_view.should_append_slash = False
|
if iscoroutinefunction(view_func):
|
||||||
return wrapper_view
|
|
||||||
|
async def _view_wrapper(request, *args, **kwargs):
|
||||||
|
return await view_func(request, *args, **kwargs)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
def _view_wrapper(request, *args, **kwargs):
|
||||||
|
return view_func(request, *args, **kwargs)
|
||||||
|
|
||||||
|
_view_wrapper.should_append_slash = False
|
||||||
|
|
||||||
|
return wraps(view_func)(_view_wrapper)
|
||||||
|
|
|
@ -237,6 +237,7 @@ Decorators
|
||||||
|
|
||||||
* :func:`~django.views.decorators.cache.cache_control`
|
* :func:`~django.views.decorators.cache.cache_control`
|
||||||
* :func:`~django.views.decorators.cache.never_cache`
|
* :func:`~django.views.decorators.cache.never_cache`
|
||||||
|
* :func:`~django.views.decorators.common.no_append_slash`
|
||||||
* ``xframe_options_deny()``
|
* ``xframe_options_deny()``
|
||||||
* ``xframe_options_sameorigin()``
|
* ``xframe_options_sameorigin()``
|
||||||
* ``xframe_options_exempt()``
|
* ``xframe_options_exempt()``
|
||||||
|
|
|
@ -83,6 +83,7 @@ view functions:
|
||||||
|
|
||||||
* :func:`~django.views.decorators.cache.cache_control`
|
* :func:`~django.views.decorators.cache.cache_control`
|
||||||
* :func:`~django.views.decorators.cache.never_cache`
|
* :func:`~django.views.decorators.cache.never_cache`
|
||||||
|
* :func:`~django.views.decorators.common.no_append_slash`
|
||||||
* ``xframe_options_deny()``
|
* ``xframe_options_deny()``
|
||||||
* ``xframe_options_sameorigin()``
|
* ``xframe_options_sameorigin()``
|
||||||
* ``xframe_options_exempt()``
|
* ``xframe_options_exempt()``
|
||||||
|
|
|
@ -147,3 +147,7 @@ customization of :class:`~django.middleware.common.CommonMiddleware` behavior.
|
||||||
|
|
||||||
This decorator allows individual views to be excluded from
|
This decorator allows individual views to be excluded from
|
||||||
:setting:`APPEND_SLASH` URL normalization.
|
:setting:`APPEND_SLASH` URL normalization.
|
||||||
|
|
||||||
|
.. versionchanged:: 5.0
|
||||||
|
|
||||||
|
Support for wrapping asynchronous view functions was added.
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
from asgiref.sync import iscoroutinefunction
|
||||||
|
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.test import SimpleTestCase
|
||||||
|
from django.views.decorators.common import no_append_slash
|
||||||
|
|
||||||
|
|
||||||
|
class NoAppendSlashTests(SimpleTestCase):
|
||||||
|
def test_wrapped_sync_function_is_not_coroutine_function(self):
|
||||||
|
def sync_view(request):
|
||||||
|
return HttpResponse()
|
||||||
|
|
||||||
|
wrapped_view = no_append_slash(sync_view)
|
||||||
|
self.assertIs(iscoroutinefunction(wrapped_view), False)
|
||||||
|
|
||||||
|
def test_wrapped_async_function_is_coroutine_function(self):
|
||||||
|
async def async_view(request):
|
||||||
|
return HttpResponse()
|
||||||
|
|
||||||
|
wrapped_view = no_append_slash(async_view)
|
||||||
|
self.assertIs(iscoroutinefunction(wrapped_view), True)
|
||||||
|
|
||||||
|
def test_no_append_slash_decorator(self):
|
||||||
|
@no_append_slash
|
||||||
|
def sync_view(request):
|
||||||
|
return HttpResponse()
|
||||||
|
|
||||||
|
self.assertIs(sync_view.should_append_slash, False)
|
||||||
|
self.assertIsInstance(sync_view(HttpRequest()), HttpResponse)
|
||||||
|
|
||||||
|
async def test_no_append_slash_decorator_async_view(self):
|
||||||
|
@no_append_slash
|
||||||
|
async def async_view(request):
|
||||||
|
return HttpResponse()
|
||||||
|
|
||||||
|
self.assertIs(async_view.should_append_slash, False)
|
||||||
|
self.assertIsInstance(await async_view(HttpRequest()), HttpResponse)
|
Loading…
Reference in New Issue