Fixed #34062 -- Updated View.http_method_not_allowed() to support async.
As with the options() methods, wrap the response in a coroutine if the view is async. Co-authored-by: Carlton Gibson <carlton.gibson@noumenal.es>
This commit is contained in:
parent
19e6efa50b
commit
9b0c9821ed
|
@ -148,7 +148,16 @@ class View:
|
||||||
request.path,
|
request.path,
|
||||||
extra={"status_code": 405, "request": request},
|
extra={"status_code": 405, "request": request},
|
||||||
)
|
)
|
||||||
return HttpResponseNotAllowed(self._allowed_methods())
|
response = HttpResponseNotAllowed(self._allowed_methods())
|
||||||
|
|
||||||
|
if self.view_is_async:
|
||||||
|
|
||||||
|
async def func():
|
||||||
|
return response
|
||||||
|
|
||||||
|
return func()
|
||||||
|
else:
|
||||||
|
return response
|
||||||
|
|
||||||
def options(self, request, *args, **kwargs):
|
def options(self, request, *args, **kwargs):
|
||||||
"""Handle responding to requests for the OPTIONS HTTP verb."""
|
"""Handle responding to requests for the OPTIONS HTTP verb."""
|
||||||
|
|
|
@ -39,3 +39,7 @@ Bugfixes
|
||||||
* Fixed a regression in Django 4.1 that didn't alter a sequence type when
|
* Fixed a regression in Django 4.1 that didn't alter a sequence type when
|
||||||
altering type of pre-Django 4.1 serial columns on PostgreSQL
|
altering type of pre-Django 4.1 serial columns on PostgreSQL
|
||||||
(:ticket:`34058`).
|
(:ticket:`34058`).
|
||||||
|
|
||||||
|
* Fixed a regression in Django 4.1 that caused a crash for :class:`View`
|
||||||
|
subclasses with asynchronous handlers when handling non-allowed HTTP methods
|
||||||
|
(:ticket:`34062`).
|
||||||
|
|
|
@ -6,8 +6,8 @@ from asgiref.sync import async_to_sync
|
||||||
|
|
||||||
from django.core.cache import DEFAULT_CACHE_ALIAS, caches
|
from django.core.cache import DEFAULT_CACHE_ALIAS, caches
|
||||||
from django.core.exceptions import ImproperlyConfigured, SynchronousOnlyOperation
|
from django.core.exceptions import ImproperlyConfigured, SynchronousOnlyOperation
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse, HttpResponseNotAllowed
|
||||||
from django.test import SimpleTestCase
|
from django.test import RequestFactory, SimpleTestCase
|
||||||
from django.utils.asyncio import async_unsafe
|
from django.utils.asyncio import async_unsafe
|
||||||
from django.views.generic.base import View
|
from django.views.generic.base import View
|
||||||
|
|
||||||
|
@ -119,6 +119,25 @@ class ViewTests(SimpleTestCase):
|
||||||
|
|
||||||
self.assertIsInstance(response, HttpResponse)
|
self.assertIsInstance(response, HttpResponse)
|
||||||
|
|
||||||
|
def test_http_method_not_allowed_responds_correctly(self):
|
||||||
|
request_factory = RequestFactory()
|
||||||
|
tests = [
|
||||||
|
(SyncView, False),
|
||||||
|
(AsyncView, True),
|
||||||
|
]
|
||||||
|
for view_cls, is_coroutine in tests:
|
||||||
|
with self.subTest(view_cls=view_cls, is_coroutine=is_coroutine):
|
||||||
|
instance = view_cls()
|
||||||
|
response = instance.http_method_not_allowed(request_factory.post("/"))
|
||||||
|
self.assertIs(
|
||||||
|
asyncio.iscoroutine(response),
|
||||||
|
is_coroutine,
|
||||||
|
)
|
||||||
|
if is_coroutine:
|
||||||
|
response = asyncio.run(response)
|
||||||
|
|
||||||
|
self.assertIsInstance(response, HttpResponseNotAllowed)
|
||||||
|
|
||||||
def test_base_view_class_is_sync(self):
|
def test_base_view_class_is_sync(self):
|
||||||
"""
|
"""
|
||||||
View and by extension any subclasses that don't define handlers are
|
View and by extension any subclasses that don't define handlers are
|
||||||
|
|
Loading…
Reference in New Issue