django - 带有 aiohttp 客户端的异步 Django 3.1
问题描述
现在是否有可能在开始将 django 移植到异步后使用 django 的 aiohttp 客户端?
我的情况:
- 服务器收到请求;
- 服务器向另一台服务器发送另一个请求;
- 服务器解码响应,将其保存到数据库中,并将响应返回给客户端;
Andrew Svetlov 在两年前提到 aiohttp“从未打算与同步 WSGI 一起工作”。( https://github.com/aio-libs/aiohttp/issues/3357 )
但现在情况如何?Django 似乎几乎支持异步视图。我们可以将 aiohttp 与 asgi django 一起使用吗?
我知道,我可以创建一个处理请求的 aiohttp 服务器,然后填充一些队列,以及将响应保存到数据库中的队列处理程序,但是在这里我从 django 中遗漏了很多:ORM、admin 等。
解决方案
你可以像这样在 Django 3.1 中实现这个场景:
async def my_proxy(request):
async with ClientSession() as session:
async with session.get('https://google.com') as resp:
print(resp.status)
print(await resp.text())
但对我来说最大的问题是如何在 django 项目中共享一个 aiohttp 会话,因为强烈建议不要为每个请求生成一个新的 ClientSession。
重要提示:当然,您应该使用一些兼容的应用程序服务器(例如 uvicorn)以 ASGI 模式运行 django 应用程序:
uvicorn my_project.asgi:application --reload
更新:我找到了解决方法。您可以使用共享全局对象创建一个模块(文件 *.py),并在项目启动时使用项目设置中的 ClientSession 实例填充它:
共享的.py:
from typing import Optional
from aiohttp import ClientSession
AIOHTTP_SESSION: Optional[ClientSession] = None
设置.py:
from aiohttp import ClientSession
from my_project import shared
...
shared.AIOHTTP_SESSION = ClientSession()
视图.py:
from my_project import shared
async def my_proxy(request):
async with shared.AIOHTTP_SESSION.get('https://google.com') as resp:
print(resp.status, resp._session)
await resp.text()
重要 - 进口应该完全相同。当我将它们更改为“从 my_project.shared 导入 AIOHTTP_SESSION”时,我的测试刹车:(
测试.py:
from asyncio import gather
from aiohttp import ClientSession
from django.test import TestCase
from my_project import shared
class ViewTests(TestCase):
async def test_async_view(self):
shared.AIOHTTP_SESSION = ClientSession()
await gather(*[self.async_client.get('/async_view_url') for _ in range(3)])
通过 ./manage.py test 运行测试
推荐阅读
- python - 如何在使用每个功能连接到数据库时保持干燥?
- api - WhatsApp 中是否有协调传入请求和管理它们的功能?
- python - 如何计算用户使用 tkinter 输入的 2 个值的百分比
- python - Tensorflow 错误:在深度强化学习中训练网络时“没有为任何变量提供梯度”
- mips - MIPS 和 RISC-V 的区别
- visual-studio-code - VSCode 用户输入法(扩展开发API)
- python - 如何纠正django中的帐户激活错误
- vue.js - 如何改变 vue-toasted 弹出的方向
- pine-script - 忽略先前的值
- python - 我成功下载了烧瓶,但“ModuleNotFoundError:没有名为‘app’的模块”