Django 模型对象作为 celery 任务的参数引发 EncodeError - 'someModelName 类型的对象不可 JSON 序列化'

aut*_*ate 3 django celery python-3.x

我正在处理一个 django 项目(我对 django 还很陌生),并遇到了在我的视图和 celery 任务之间传递模型对象的问题。

我正在从包含多个ModelChoiceField字段的表单中获取输入,并在 celery 任务中使用选定的对象。当我使用 someTask.delay(x, y, z) 对任务进行排队(从视图中的 post 方法)时,其中 x、y 和 z 是 ModelChoiceFields 表单中的各种对象,我收到错误object of type <someModelName> is not JSON serializable

也就是说,如果我创建一个简单的测试函数并将任何相同的对象从表单传递到函数中,我会得到预期的行为,并且会记录表单中所选对象的名称。

def test(object):
    logger.debug(object.name)
Run Code Online (Sandbox Code Playgroud)

我根据上述错误做了一些探索,发现django 序列化器可以通过在将serializers.serialize('json', [template]),视图中使用的对象传递给 celery 任务之前序列化该对象来实现解决方法。

然后,我可以通过使用访问其所需位作为字典来访问 celery 任务中的对象template = json.loads(template)[0].get('fields')- 虽然这有效,但它看起来确实有点不优雅,我想看看这里是否缺少一些东西。

我显然愿意接受任何反馈/指导,但我的主要问题是:

  • 为什么object...is not JSON serializable在将模型对象传递给 celery 任务时会出现错误,而在传递给简单的测试函数时却不会出现错误?

  • 在对 celery 任务进行排队之前使用 django 序列化器的方法是否被认为是可接受/正确的,或者是否有更干净的方法来实现此目标?

任何建议将不胜感激。

回溯:我也尝试在这里发布完整的回溯,但是包括这导致该帖子被标记为“这看起来像垃圾邮件”

Internal Server Error: /build/
Traceback (most recent call last):
  File "/home/tech/sandbox_project/venv/lib/python3.8/site-packages/kombu/serialization.py", line 49, in _reraise_errors
    yield
  File "/home/tech/sandbox_project/venv/lib/python3.8/site-packages/kombu/serialization.py", line 220, in dumps
    payload = encoder(data)
  File "/home/tech/sandbox_project/venv/lib/python3.8/site-packages/kombu/utils/json.py", line 65, in dumps
    return _dumps(s, cls=cls or _default_encoder,
  File "/usr/lib/python3.8/json/__init__.py", line 234, in dumps
    return cls(
  File "/usr/lib/python3.8/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.8/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/home/tech/sandbox_project/venv/lib/python3.8/site-packages/kombu/utils/json.py", line 55, in default
    return super().default(o)
  File "/usr/lib/python3.8/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Template is not JSON serializable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/tech/sandbox_project/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
Run Code Online (Sandbox Code Playgroud)

Rai*_*bir 6

将此行添加到settings.py

# Project/settings.py
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
Run Code Online (Sandbox Code Playgroud)

然后,id/pk如果您使用模型实例调用任务,则不要传递对象,而是发送 JSON,如下所示。

test.delay({'pk': 1})
Run Code Online (Sandbox Code Playgroud)

Django 模型实例在 celery 环境中不可用,因为它在不同的进程中运行,

那么如何在任务中获取模型实例呢?好吧,你可以做如下的事情 -

test.delay({'pk': 1})
Run Code Online (Sandbox Code Playgroud)