从Django代码调用芹菜任务的正确方法?

时间:2015-06-18 21:52:56

标签: python django celery djcelery

我有一个注册表单,在提交后,我想通过一些外部API执行一些数据验证,然后最终提交给另一个API。我想以异步方式执行此操作,因此提交者不会等待表单提交10秒。

到目前为止,这是我的代码 - 它可以工作,但是如果在任务中抛出异常,则用户会收到500错误(特定的例外情况是有时我使用的第三方API超时)。我的印象是,如果任务是异步执行的(注意@task装饰器并使用延迟来调用任务),那么无论函数中发生了什么,都应该发生成功页面加载。

views.py

from myapp.tasks import prepare_and_submit_data

def register(request):
  form = SignupForm(request.POST or None)
  if form.is_valid():

    # Async function.
    prepare_and_submit_data.delay(form.cleaned_data)

    return render(request, 'success.html', {})
  return render(request, 'signup.html', {'form': form})

tasks.py

from celery.decorators import task

@task
def prepare_and_submit_data(data):
  # do some external API requests and modify data
  data = requests.post(BASE_URL, data=data).json()
  # ...

使用try / except子句包装prepare_and_submit_data的内容是正确的解决方案并记录错误吗?或者将函数的调用包装在寄存器中?

谢谢。

1 个答案:

答案 0 :(得分:0)

如果任务是异步执行的,则延迟调用是非阻塞的,它只是将任务放入消息队列中并立即继续执行您的视图代码,这意味着无论任务是否成功或失败,它不会对视图的代码产生任何影响。本声明的例外情况是:

  • 如果由于某种原因导致任务排队失败,例如您的邮件队列无法访问,因此无法安排任务,在这种情况下,您在调用prepare_and_submit_data.delay

  • 时会收到异常
  • CELERY_ALWAYS_EAGER设置为True,这意味着即使您明确要求异步执行任务,它也会同步执行,这是相同的好像你只是定期调用阻止函数(prepare_and_submit_data()

我的赌注是后一种情况,你已经正确编写了代码,但上面提到的设置强制它同步执行。但有一点需要考虑,几乎可以肯定的是,当您的视图返回响应时,您无法获得异步任务的结果。因此,如果您打算在执行视图期间使用异步验证的结果,那么您不需要异步运行它,而是从一开始就经常进行同步执行。但是,如果您只需要稍后使用它,一种常见的技术是使用从客户端到单独的API端点的定期ajax请求,这应该检查您的任务是否完成了它并执行并返回结果。