如何在DRF中使用基于异步函数的视图?

问题描述 投票:0回答:4

由于 Django 现在支持异步视图,我正在尝试将包含大量基于函数的视图的代码库更改为异步视图,但由于某种原因它不起作用。

@api_view(["GET"])
async def test_async_view(request):
    ...
    data = await get_data()
    return Response(data)

当我向此端点发送请求时,我收到一条错误消息:

断言错误:需要

Response
HttpResponse
HttpStreamingResponse
从视图中返回,但收到了
<class 'coroutine'>

DRF还不支持异步视图吗?我可以采取其他替代方法来使其正常工作吗?

python django asynchronous django-rest-framework
4个回答
11
投票

截至目前,DRF 不支持异步“api 视图”。这是 DRF 社区中的一个开放的问题 (#7260),目前仍处于讨论阶段。

但是,Django 提供了一个装饰器/包装器,它允许我们使用

sync_to_async(...)

 包装器将同步视图/函数转换为异步。

例如,

@sync_to_async @api_view(["GET"]) def sample_view(request): data = get_data() return Response(data)
请注意,此处 

sample_view(...)

get_data(...)
 是同步功能。


2
投票
你可以用

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})
    

0
投票
我认为你可以在DRF中使用这个装饰器

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): ...
    

0
投票

所有 Іѕ Vаиітy 的答案都有效,尽管 ardf

 仅与 
Django>=4.1
 兼容
    

© www.soinside.com 2019 - 2024. All rights reserved.