【问题标题】:The right way to perform a task asynchronously in Django, via Celery通过 Celery 在 Django 中异步执行任务的正确方法
【发布时间】:2016-09-28 19:16:40
【问题描述】:

我有一个模仿 Instagram 的 Django 应用程序,用户上传照片或模因,然后他们的粉丝会收到有关照片的通知。

目前,为了发送通知,一旦用户上传照片,我会遍历上传者拥有的每个粉丝,将通知附加到列表中,然后bulk_create 对象。如:

    fans = UserFan.objects.filter(star=user).values_list('fan',flat=True)
    fan_list = []
    for fan in fans:
        fan_list.append(PhotoObjectSubscription(viewer_id=fan, which_photo=photo, updated_at=time, seen=False, type_of_object='1'))
    PhotoObjectSubscription.objects.bulk_create(fan_list)

简单的东西。请注意,我还在应用程序的 VM 上安装了 supervisord,我通过 celery 运行一些基本任务(redis 作为消息代理)。

现在我想以celery task 的身份执行上面的bulk_create 任务;异步。我的bulk_create 代码位于用于处理照片上传的同一视图中,因此我认为异步执行此操作将为用户加快该过程。

我是celery 任务的新手,所以有人可以通过说明性示例指出我如何将上述bulk_create 任务变成celery 任务吗?我已经完成了研究,这就是我认为我需要做的事情:

1) 在bulk_create 语句末尾添加delay()

PhotoObjectSubscription.objects.bulk_create(fan_list).delay()

2) 在tasks.py中,添加一个新的任务来处理上面的内容:

@task
def bulk_create_notifications():
    PhotoObjectSubscription.objects.bulk_create(fan_list)

3) 无需在settings.py 中向CELERYBEAT_SCHEDULE 添加任何内容,因为该任务不是周期性任务。

我可能不完全正确,所以请帮忙。

【问题讨论】:

    标签: python django celery django-celery celery-task


    【解决方案1】:

    您需要传递fans(如果它实际上是ValuesListQuerySet,您可能必须将其转换为list)和任务需要的所有其他东西(例如photo.id)作为任务的参数:

    @task
    def bulk_create_notifications(fans, photo_id):
        fan_list = []
        for fan in fans:
            fan_list.append(PhotoObjectSubscription(viewer_id=fan, which_photo_id=photo_id, updated_at=time, seen=False, type_of_object='1'))
        PhotoObjectSubscription.objects.bulk_create(fan_list)
    

    然后,您可以通过以下方式异步启动任务:

    # call delay on the task and pass it the same params you would pass to the fnc itself
    bulk_create_notifications.delay(fans)  
    

    由于参数需要由任务队列 (redis) 存储和通信,因此您只能传递可由您在设置中设置的序列化程序(可能是 JSON)可序列化的参数。这意味着您应该坚持使用简单类型 s.a.字符串、整数,您不能将模型实例或其列表作为参数传递。

    您当然可以开始更高,只需通过 user.id 并完成任务中的所有数据库工作。

    【讨论】:

    • 没有。那是我误读了你的代码。我已经在答案中更改了它。你不能传递模型实例!当您在True 设置 CELERY_ALWAYS_EAGER 时,它可能在您的开发环境中工作,但参数实际上是通过队列传递的。
    • @HassanBaig 实际上,您的代码中的fans 是一个ValuesListQuerySet,您应该在将其传递给任务之前将其转换为list
    • 知道了。我要试试这个,稍后再回复你!
    • 问题:在views.py中,我有bulk_create_notifications.delay(fans),我是否也应该在文件顶部添加from myapp/links import bulk_create_notifications。我应该像对待任何其他方法一样对待它吗?
    • @HassanBaig 是的,就像其他人一样。请注意,您仍然可以作为普通方法调用。译员必须知道该名称。我喜欢将我的任务保存在名为 tasks.py 的应用级模块中。
    猜你喜欢
    • 2011-11-22
    • 2016-12-13
    • 2011-10-22
    • 2019-01-22
    • 1970-01-01
    • 2016-09-23
    • 1970-01-01
    • 2014-12-01
    • 2019-05-31
    相关资源
    最近更新 更多