6

我有以下代码:

@task()
def handle_upload(title, temp_file, user_id):
    .
    .
    .
    photo.save()
    #if i insert here "photo2 = Photo.objects.get(pk=photo.pk)" it works, including the         view function
    return photo.pk

#view function
def upload_status(request):
    task_id = request.POST['task_id']

    async_result = AsyncResult(task_id)
    photo_id = async_result.get()
    if async_result.successful(): 
        photo = Photo.objects.get(pk=photo_id)

我使用 ajax 请求来检查上传的文件,但是在 celery 任务完成后,我得到一个照片匹配查询不存在。照片 pk 确实存在并被返回。如果我手动查询数据库,它可以工作。这是某种数据库滞后吗?我该如何解决?我正在使用 Django 1.4 和 Celery 3.0

4

1 回答 1

2

您可以通过在 django 视图中添加延迟以在任务成功完成几秒钟后等待来确认这是否是延迟问题。如果这解决了问题,您可能希望将 handle_upload 包装在事务中以阻塞,直到数据库完全确认它在返回之前完成。

除了 Django,DB 也有自己的缓存。当 django 调用查询集时,它要么从自己的缓存中获取陈旧数据(除非您正在重用查询集,我在您发布的代码部分中没有看到)或者数据库正在缓存相同 Django 连接的结果。

例如,如果您要在 celery 任务在一个全新的 django 请求/视图中完成后调用后处理,您可能会看到 DB 中的新更改很好。但是,由于您的视图在任务执行时被阻止(这违背了 celery 顺便说一句的目的),因此 django 仅在进入视图时保留数据库的快照。因此,您的 get 失败并且您在简单地进入 django shell 时直接确认了此行为。

您可以通过以下任一方式解决此问题:

  • 调用将刷新快照的事务管理
  • 更改您的数据库端点缓存和自动提交策略
  • 完成处理后,让 celery 回调 django(网络请求)(这可能是您无论如何都想做的,因为阻止 django 会破坏目的)
于 2012-07-18T12:19:53.230 回答