kombu.exceptions.EncodeError:用户不可JSON序列化

use*_*277 3 python django json celery celery-task

我有celery 4.1.0的django 1.11.5应用程序,我一直都收到了:

kombu.exceptions.EncodeError: <User: testuser> is not JSON serializable
Run Code Online (Sandbox Code Playgroud)

我的settings.py:

CELERY_BROKER_URL = 'amqp://localhost'
CELERY_RESULT_BACKEND = 'amqp://localhost'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Makassar'
CELERY_BEAT_SCHEDULE = {}
Run Code Online (Sandbox Code Playgroud)

task.py

from __future__ import absolute_import, unicode_literals
from celery import task
from django.contrib.auth.models import User


@task(serializer='json')
def task_number_one():
    user = User.objects.create(username="testuser", email="test@test.com", password="pass")
    return user
Run Code Online (Sandbox Code Playgroud)

在视图中我调用任务:

def form_valid(self, form):
    form.instance.user = self.request.user
    task_number_one.delay()
    return super().form_valid(form)
Run Code Online (Sandbox Code Playgroud)

JPG*_*JPG 14

该错误是因为 CeleryJSON在您返回User实例时期望从您的任务函数中获取数据。

如何解决这个问题?
您没有在任何地方使用该返回数据,因此您不必返回它。那就是您可以return user从任务功能中删除。
或者,从任务函数
返回Json数据也可以解决这个问题

解决方案 1

@task(serializer='json')
def task_number_one():
    user = User.objects.create(username="testuser", email="test@test.com", password="pass")
Run Code Online (Sandbox Code Playgroud)


解决方案2

@task(serializer='json')

def task_number_one():
    user = User.objects.create(username="testuser", email="test@test.com", password="pass")
    # return some json data instead of `USER` instance
    return {"status": True}  # Change is here
Run Code Online (Sandbox Code Playgroud)


MrN*_*ame 5

这是因为您使用JSON序列化程序进行任务序列化(如设置所示CELERY_TASK_SERIALIZER = 'json'),但是您尝试返回模型实例(无法序列化为JSON)。

您有两种选择:

1)不要传递实例,传递实例的主键,然后在任务中查找对象。

2)使用pickle任务串行代替。这将使您可以将对象作为参数传递给任务并返回它们,但这本身就是安全问题

  • 对于几乎类似的情况(当尝试将对象或类实例作为任务中的参数传递时),答案是正确的,但对于所提出的问题则不是。对于这个问题,@JPG 是正确的 (2认同)