由于 Django 现在支持异步视图,我正在尝试将包含大量基于函数的视图的代码库更改为异步视图,但由于某种原因它不起作用。
@api_view(["GET"])
async def test_async_view(request):
...
data = await get_data()
return Response(data)
当我向此端点发送请求时,我收到一条错误消息:
断言错误:需要
、Response
或HttpResponse
从视图中返回,但收到了HttpStreamingResponse
<class 'coroutine'>
DRF还不支持异步视图吗?我可以采取其他替代方法来使其正常工作吗?
截至目前,DRF 不支持异步“api 视图”。这是 DRF 社区中的一个开放的问题 (#7260),目前仍处于讨论阶段。
但是,Django 提供了一个装饰器/包装器,它允许我们使用 包装器将同步视图/函数转换为异步。 例如,
@sync_to_async
@api_view(["GET"])
def sample_view(request):
data = get_data()
return Response(data)
请注意,此处 sample_view(...)
和
get_data(...)
是同步功能。
adrf
来做到这一点:
pip install adrf
然后将其添加到 INSTALLED_APPS
INSTALLED_APPS = [
...
'adrf',
]
import asyncio
from asgiref.sync import sync_to_async
@sync_to_async
def do_a_network_call(some_input):
expensive_result = do_expensive_network_call(some_input)
return expensive_result
# Class Based Views:
from adrf.views import APIView
class AsyncView(APIView):
async def get(self, request):
result = await asyncio.gather(do_a_network_call("some_input"))
return Response({"result": result})
# Function Based Views:
from adrf.decorators import api_view
@api_view(['GET'])
async def async_view(request):
result = await asyncio.gather(do_a_network_call("some_input"))
return Response({"result": result})
import asyncio
from functools import wraps
def to_async(blocking):
@wraps(blocking)
def run_wrapper(*args, **kwargs):
return asyncio.run(blocking(*args, **kwargs))
return run_wrapper
使用示例
@to_async
@api_view(["GET"])
async def sample_view(request):
...