微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

可以在 django 中异步执行数据库操作吗? 尚不支持但正在开发中如果你需要排队调用数据库,我们曾经使用像celery或rabbitMQ这样的任务队列

如何解决可以在 django 中异步执行数据库操作吗? 尚不支持但正在开发中如果你需要排队调用数据库,我们曾经使用像celery或rabbitMQ这样的任务队列

我正在编写一个命令,在数据库随机创建 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)

如果你需要排队调用数据库,我们曾经使用像celery或rabbitMQ这样的任务队列。

  • 顺便说一句,如果你真的知道你在做什么,你可以称之为但你的责任 只需关闭异步安全,但要注意数据丢失和完整性错误
#settings.py
DJANGO_ALLOW_ASYNC_UNSAFE=True

在 Django 中需要这样做的原因是许多库,特别是数据库适配器,要求在创建它们的同一个线程中访问它们。此外,许多现有的 Django 代码假定它们都在同一个线程中运行,例如中间件向请求添加内容以供以后在视图中使用。

发行说明中有更多有趣的消息: https://docs.djangoproject.com/en/3.1/topics/async/

,

实现你的愿望是可能的,但是你需要一个不同的视角来解决这个问题。

尝试使用异步工作者,一个简单的方法是 rq workerscelery

使用这些库之一来处理 django 中在不同线程或进程中定义的异步长时间运行的任务。

,

你可以使用bulk_create()来创建大量的对象,这会加快进程,另外把bulk_create()放在一个单独的线程下。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。