2

我有一个 django 视图,它创建一个用户,然后将 user.pk 发送到 celery 任务(.delay),以便通过电子邮件向用户发送电子邮件,并通过一些我不想在视图中调用的 API 将用户添加到邮件列表中。

保存新用户实例后user.save(),我将其发送user.pk到 celery 任务email_user_task.delay(user.pk),但 celery 任务因用户不存在的错误而崩溃。

我尝试在 celery 任务中添加一个 try except 块,并休眠以等待视图完成,这可以工作,但在站点繁忙并尝试使用手动事务提交时会导致其他问题,但我遇到了其他错误和感觉这应该有效。

@render_to('signup.html')
def signup(request):
    if request.method == "POST":
        form = SignupForm(request.POST, request=request)
        if form.is_valid():
            new_user = form.save(commit=False)
            new_user.email = form.cleaned_data["email"]
            new_user.fist_name = form.cleaned_data["first_name"]
            new_user.last_name = form.cleaned_data["last_name"]
            new_user.save()
            email_user_task.delay(new_user.pk)  # this cannot get the User from the pk
            HttpResponseRedirect(reverse("signup_complete"))
     else:
         form = SignupForm(request=request)
     return locals()

这个芹菜任务爆炸了:

@task
def email_user_task(user_pk):
    user = User.objects.get(pk=user_pk)  # this yeilds a User.DoesNotExist error

我的第一个修复方法有效,除非 5 秒还不够:

def email_user_task(user_pk):
    try:
        user = User.objects.get(pk=user_pk)
    except User.DoesNotExist:
        import time
        time.sleep(5)
        user = User.objects.get(pk=user_pk)  # this works I'm guessing after the view finishes

我错过了什么?即为什么new_user.save()在调用 celery 任务之前不写入数据库?

4

2 回答 2

1

我遇到了同样的问题,试试这个

@render_to('signup.html')
def signup(request):
    if request.method == "POST":
        form = SignupForm(request.POST, request=request)
        if form.is_valid():
            new_user = form.save(commit=False)
            new_user.email = form.cleaned_data["email"]
            new_user.fist_name = form.cleaned_data["first_name"]
            new_user.last_name = form.cleaned_data["last_name"]
            if new_user.save():
              email_user_task.delay(new_user.pk)  # this cannot get the User from the pk
            HttpResponseRedirect(reverse("signup_complete"))
     else:
         form = SignupForm(request=request)
     return locals()
于 2013-10-05T18:53:40.240 回答
1

由于 User 对象被锁定在视图事务中并且不想弄乱事务以确保在 celery 任务尝试访问它之前将其保存,我将所有相关参数传递给 celery 任务,以便它可以射出它电子邮件。

IE

email_user_task.delay(new_user.first_name, new_user.email)
于 2013-11-16T20:03:54.357 回答