【问题标题】:Django & Celery - Accessing post_save dataDjango & Celery - 访问 post_save 数据
【发布时间】:2018-02-28 16:51:42
【问题描述】:

我尝试从 post_save 信号调用 Celery 任务。

信号是:

@receiver(post_save, sender='foo.ModelClass')
def execute_after_save(sender, instance, created, *args, **kwargs):
    special_task.apply_async(kwargs={'bar': instance.pk}, countdown=5)

任务是:

@app.task(bind=True)
def special_task(bar, *args, **kwargs):
    bar = ModelClass.objects.select_for_update().get(pk=bar)
    print('Bar attribute: %s' % bar.attribute)

在此迭代中,我收到一条错误消息 special_task() got multiple values for argument 'bar'。在我只发送 instance.pk 作为 arg 的迭代中,我得到一个 TypeError 说我需要传递一个整数。当我的信号看起来像:

@receiver(post_save, sender='foo.ModelClass')
def execute_after_save(sender, instance, created, *args, **kwargs):
    special_task.apply_async(args=(instance.pk,), countdown=5)

我收到一条错误消息,指出具有该属性的 ModelClass DoesNotExist

我查看了有关此问题的其他 SO 问题,但我不断收到相同的错误。在 Python 3.5 上使用 Django 1.11.4、Celery 3.1.25。

此任务最终会尝试选择一个新保存的 ModelClass,对其执行额外的工作,然后再次保存。我该怎么做?

[编辑:这是我的堆栈跟踪:]

[2017-09-19 12:31:01,275: ERROR/MainProcess] Task projectname.foo.tasks.special_task[476904d9-78ed-489f-a47e-2c38fe8c64c9] raised unexpected: TypeError("special_task() got multiple values for argument 'bar'",)
Traceback (most recent call last):
  File "/home/brandon/projects/python/lib/python3.5/site-packages/celery/app/trace.py", line 240, in trace_task
R = retval = fun(*args, **kwargs)
  File "/home/brandon/projects/python/lib/python3.5/site-packages/celery/app/trace.py", line 438, in __protected_call__
return self.run(*args, **kwargs)
TypeError: special_task() got multiple values for argument 'bar'

【问题讨论】:

  • special_task.apply_async(args=(instance.pk,), countdown=5) 是正确的,请提供您在此之后得到的异常的完整回溯。我预见的唯一问题是,在您正在执行的任务中 print('Bar attribute: %s' % bar.attribute) bar 是一个 pk 不是对象实例,也许您的意思是 link.attribute
  • 我在上面进行了更正,并发布了堆栈跟踪。
  • 提供此错误的回溯ModelClass with that attribute DoesNotExist
  • 我把代码改回来了,我得到了这个回溯:gist.github.com/brandonjschwartz/… 几个小时后我会有时间看看哪里出错了。

标签: python django celery


【解决方案1】:

根据您提供的最新回溯,当您使用 bind=True 时,任务的第一个参数应该是 self 参见 Bound tasks

@app.task(bind=True)
def special_task(self, bar, *args, **kwargs):
    bar = ModelClass.objects.select_for_update().get(pk=bar)
    print('Bar attribute: %s' % bar.attribute)

【讨论】:

  • 谢谢,这也回答了这个问题之外的一些问题!
猜你喜欢
  • 2017-10-02
  • 2018-07-26
  • 2014-07-10
  • 2011-05-30
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 2020-07-29
相关资源
最近更新 更多