diff --git a/rest_framework/views.py b/rest_framework/views.py index a90b4d3c0..dac7fbb57 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -2,7 +2,8 @@ Provides an APIView class that is the base of all views in REST framework. """ import asyncio -from asgiref.sync import async_to_sync + +import django from django.conf import settings from django.core.exceptions import PermissionDenied from django.db import connections, models @@ -20,6 +21,11 @@ from rest_framework.schemas import DefaultSchema from rest_framework.settings import api_settings from rest_framework.utils import formatting +if django.VERSION >= (3, 1): + from asgiref.sync import async_to_sync +else: + async_to_sync = None + def get_view_name(view): """ @@ -506,6 +512,8 @@ class APIView(View): handler = self.http_method_not_allowed if asyncio.iscoroutinefunction(handler): + if not async_to_sync: + raise Exception('Async API views are supported only for django>=3.1.') response = async_to_sync(handler)(request, *args, **kwargs) else: response = handler(request, *args, **kwargs) diff --git a/tests/test_views.py b/tests/test_views.py index 2bcee571e..61d073270 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,5 +1,7 @@ import copy +import django +import pytest from django.test import TestCase from rest_framework import status @@ -136,6 +138,10 @@ class FunctionBasedViewIntegrationTests(TestCase): assert sanitise_json_error(response.data) == expected +@pytest.mark.skipif( + django.VERSION < (3, 1), + reason="Async view support requires Django 3.1 or higher", +) class ClassBasedAsyncViewIntegrationTests(TestCase): def setUp(self): self.view = BasicAsyncView.as_view()