可以将OrderedDict作为Celery任务参数传递吗?

时间:2018-11-06 19:22:57

标签: django django-rest-framework celery django-celery ordereddict

我在Django REST Framework的序列化器中有一个被覆盖的update方法
在此update中,由于用户可以发送很多孩子,所以我有异步Celery任务process_children 来处理孩子。

class MyModelSerializer(serializers.ModelSerializer):
    ....

    @transaction.atomic
    def update(self, mymodel, validated_data):
        try:
            children_data = validated_data.pop('children')
            transaction.on_commit(lambda: process_children.apply_async(
                countdown=1,
                args=[mymodel.id, children_data]))
        except KeyError:
            pass
        ...

在args中,有一个参数不是json对象而是OrderedDict children_data

任务如下:

@app.task
def process_children(mymodel_id, children_data):
    mymodel = MyModel.objects.get(pk=mymodel_id)
    children = mymodel.children.all()
    for child_data in children_data:
        try:
            child = children.get(start=child_data['start'])
            child = populate_child(child, child_data)
            child.save()
        except Child.DoesNotExist:
            create_child(mymodel, child_data)

我读到我们应该只发送json(或泡菜,yaml,等等...)参数。

  • 但是这种设置似乎可行
  • 我什至可以发送datetime对象(即任务中使用的start属性,以将存储的子对象与通过api发送的新值进行匹配)。

那么这是怎么回事?

  • 一切正常,芹菜像老板一样对OrderedDict进行序列化和反序列化。
  • 还是我疯了,应该在调用任务之前序列化并在任务内部反序列化?

[更新,添加CELERY设置]

CELERY_BROKER_URL = get_env_variable('REDIS_URL')
CELERY_BROKER_POOL_LIMIT = 0
CELERY_REDIS_MAX_CONNECTIONS = 10
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Europe/London'

2 个答案:

答案 0 :(得分:0)

您正在使用的pickle序列化器可以相对好地处理对象,但是存在一些顾虑。 Here's a blog post on the concept of serializing and celery.

答案 1 :(得分:0)

是的,您做得正确。

doc中所述。

  

在客户端和工作人员之间传输的数据需要进行序列化,因此Celery中的每条消息都有一个content_type标头,用于描述用于对其进行编码的序列化方法。

此外,从celery 4.0开始,默认序列化器为JSON(之前pickle)。因此,无论何时调用此任务,默认情况下celery都会对其进行序列化和反序列化。 如果要使用任何其他序列化程序,则在调用任务时,需要指定content-type(如果使用.delay,则默认情况下序列化程序为json

process_children.apply_async((model_id, children_data), serializer='pickle')