Tentative async implementation

This commit is contained in:
enrico 2022-08-19 17:03:22 +08:00
parent df584350b4
commit 79ce07ba9b
2 changed files with 81 additions and 5 deletions

View File

@ -1,6 +1,8 @@
""" """
Provides an APIView class that is the base of all views in REST framework. Provides an APIView class that is the base of all views in REST framework.
""" """
import asyncio
from asgiref.sync import async_to_sync
from django.conf import settings from django.conf import settings
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db import connections, models from django.db import connections, models
@ -503,7 +505,10 @@ class APIView(View):
else: else:
handler = self.http_method_not_allowed handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs) if asyncio.iscoroutinefunction(handler):
response = async_to_sync(handler)(request, *args, **kwargs)
else:
response = handler(request, *args, **kwargs)
except Exception as exc: except Exception as exc:
response = self.handle_exception(exc) response = self.handle_exception(exc)

View File

@ -22,16 +22,24 @@ class BasicView(APIView):
return Response({'method': 'POST', 'data': request.data}) return Response({'method': 'POST', 'data': request.data})
class BasicAsyncView(APIView):
async def get(self, request, *args, **kwargs):
return Response({'method': 'GET'})
async def post(self, request, *args, **kwargs):
return Response({'method': 'POST', 'data': request.data})
@api_view(['GET', 'POST', 'PUT', 'PATCH']) @api_view(['GET', 'POST', 'PUT', 'PATCH'])
def basic_view(request): def basic_view(request):
if request.method == 'GET': if request.method == 'GET':
return {'method': 'GET'} return Response({'method': 'GET'})
elif request.method == 'POST': elif request.method == 'POST':
return {'method': 'POST', 'data': request.data} return Response({'method': 'POST', 'data': request.data})
elif request.method == 'PUT': elif request.method == 'PUT':
return {'method': 'PUT', 'data': request.data} return Response({'method': 'PUT', 'data': request.data})
elif request.method == 'PATCH': elif request.method == 'PATCH':
return {'method': 'PATCH', 'data': request.data} return Response({'method': 'PATCH', 'data': request.data})
class ErrorView(APIView): class ErrorView(APIView):
@ -72,6 +80,23 @@ class ClassBasedViewIntegrationTests(TestCase):
def setUp(self): def setUp(self):
self.view = BasicView.as_view() self.view = BasicView.as_view()
def test_get_succeeds(self):
request = factory.get('/', content_type='application/json')
response = self.view(request)
assert response.status_code == status.HTTP_200_OK
assert response.data == {'method': 'GET'}
# def test_post_succeeds(self):
# request = factory.post('/', {"test": "foo"}, content_type='application/json')
# response = self.view(request)
# import pdb; pdb.set_trace()
# expected = {
# 'method': 'POST',
# 'data': {'test': 'foo'}
# }
# assert response.status_code == status.HTTP_200_OK
# assert response.data == expected
def test_400_parse_error(self): def test_400_parse_error(self):
request = factory.post('/', 'f00bar', content_type='application/json') request = factory.post('/', 'f00bar', content_type='application/json')
response = self.view(request) response = self.view(request)
@ -86,6 +111,52 @@ class FunctionBasedViewIntegrationTests(TestCase):
def setUp(self): def setUp(self):
self.view = basic_view self.view = basic_view
def test_get_succeeds(self):
request = factory.get('/', content_type='application/json')
response = self.view(request)
assert response.status_code == status.HTTP_200_OK
assert response.data == {'method': 'GET'}
# def test_post_succeeds(self):
# request = factory.post('/', {'test': 'foo'}, content_type='application/json')
# response = self.view(request)
# expected = {
# 'method': 'POST',
# 'data': {'test': 'foo'}
# }
# assert response.status_code == status.HTTP_200_OK
# assert response.data == expected
def test_400_parse_error(self):
request = factory.post('/', 'f00bar', content_type='application/json')
response = self.view(request)
expected = {
'detail': JSON_ERROR
}
assert response.status_code == status.HTTP_400_BAD_REQUEST
assert sanitise_json_error(response.data) == expected
class ClassBasedAsyncViewIntegrationTests(TestCase):
def setUp(self):
self.view = BasicAsyncView.as_view()
def test_get_succeeds(self):
request = factory.get('/', content_type='application/json')
response = self.view(request)
assert response.status_code == status.HTTP_200_OK
assert response.data == {'method': 'GET'}
# def test_post_succeeds(self):
# request = factory.post('/', {'test': 'foo'}, content_type='application/json')
# response = self.view(request)
# expected = {
# 'method': 'POST',
# 'data': {'test': 'foo'}
# }
# assert response.status_code == status.HTTP_200_OK
# assert response.data == expected
def test_400_parse_error(self): def test_400_parse_error(self):
request = factory.post('/', 'f00bar', content_type='application/json') request = factory.post('/', 'f00bar', content_type='application/json')
response = self.view(request) response = self.view(request)