django - 可以在 django 中异步执行数据库操作吗?
问题描述
我正在编写一个命令来在数据库中随机创建 500 万个订单。
def constrained_sum_sample(
number_of_integers: int, total: Optional[int] = 5000000
) -> int:
"""Return a randomly chosen list of n positive integers summing to total.
Args:
number_of_integers (int): The number of integers;
total (Optional[int]): The total sum. Defaults to 5000000.
Yields:
(int): The integers whose the sum is equals to total.
"""
dividers = sorted(sample(range(1, total), number_of_integers - 1))
for i, j in zip(dividers + [total], [0] + dividers):
yield i - j
def create_orders():
customers = Customer.objects.all()
number_of_customers = Customer.objects.count()
for customer, number_of_orders in zip(
customers,
constrained_sum_sample(number_of_integers=number_of_customers),
):
for _ in range(number_of_orders):
create_order(customer=customer)
number_of_customers
将至少大于 1k 并且该create_order
函数至少执行 5 db 操作(一个用于创建订单,一个用于随机获取订单的商店,一个用于创建订单项目(最多可以达到 30 个,也是随机的),一个用于获取项目的产品(或更高但等于该项目),另一个用于创建销售说明。
您可能会怀疑这需要很长时间才能完成。我尝试过异步执行这些操作,但没有成功。我的所有尝试(至少十几个;其中大多数使用sync_to_async
)都引发了以下错误:
SynchronousOnlyOperation you cannot call this from an async context - use a thread or sync_to_async
在我继续破脑袋之前,我问:有没有可能实现我的愿望?如果是这样,我应该如何进行?
非常感谢!
解决方案
尚不支持,但正在开发中。
Django 3.1 正式支持视图和中间件的异步,但是如果您尝试在异步函数中调用 ORM,您将获得 SynchronousOnlyOperation。
如果您需要从 async 函数调用 DB,他们提供了帮助工具,例如:async_to_sync 和 sync_to_async 在线程模式或协程模式之间切换,如下所示:
from asgiref.sync import sync_to_async
results = await sync_to_async(Blog.objects.get, thread_sensitive=True)(pk=123)
如果您需要对 DB 的调用进行排队,我们曾经使用 celery 或 rabbitMQ 之类的任务队列。
- 顺便说一句,如果你真的知道你在做什么,你可以调用它,但你的责任只是关闭异步安全,但要注意数据丢失和完整性错误
#settings.py
DJANGO_ALLOW_ASYNC_UNSAFE=True
在 Django 中需要这样做的原因是,许多库,特别是数据库适配器,要求在创建它们的同一线程中访问它们。此外,许多现有的 Django 代码假定它们都在同一个线程中运行,例如中间件添加请求以后在视图中使用的东西。
发行说明中的更多有趣新闻: https ://docs.djangoproject.com/en/3.1/topics/async/
推荐阅读
- git - 无法将 NUnit 测试项目添加到源代码管理 (Git)?
- dask - Dask read_csv 失败
- unit-testing - 如何将特征对象的存根注入 Rust 中的类型并保留对它的引用?
- arduino - 向 Arduino 发送连续剧的方式有所不同
- javascript - 如果 .js 文件不存在,则包含 jQuery
- r - 使用 R 比较一个地区的多个 5 年 ACS 估计值
- android - 需要一些帮助:任务':app:processDebugResources'的执行失败
- python - 数据帧到 csv - csv 文件未保存到本地桌面
- c++ - 如何修复在抛出“std::logic_error”实例后调用的终止 what(): basic_string::_M_construct null not valid
- python-3.x - Ansible(控制节点)可以报告它使用的 Python 版本吗?