简体   繁体   English

在Celery任务中保存对象后,Django匹配查询不存在

[英]Django matching query does not exist after object save in Celery task

I have the following code: 我有以下代码:

@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)

I use an ajax request to check for the uploaded file but after the celery task finishes i get a Photo matching query does not exist. 我使用ajax请求检查上传的文件,但是在celery任务完成后,我得到一个不存在照片匹配查询。 The photo pk does exist and gets returned. 照片pk确实存在并返回。 If i query the database manually it works. 如果我手动查询数据库,它将起作用。 Is this some sort of database lag? 这是某种数据库滞后吗? How can I fix it? 我该如何解决? I'm using Django 1.4 and Celery 3.0 我正在使用Django 1.4和Celery 3.0

You can confirm if it is a lag issue by adding a delay to your django view to wait after the task has successfully finished for aa few seconds. 您可以通过在您的django视图中添加延迟来确认是否是滞后问题,以在任务成功完成几秒钟后等待。 If that resolves the problem you might want to wrap the handle_upload in a transaction to block until the db has completely confirmed it has finished before returning. 如果这样可以解决问题,则可能需要将handle_upload包装在事务中以阻塞,直到数据库在返回之前完全确认它已完成。

Beside Django, DB too has its own caches. 除了Django外,DB也有自己的缓存。 When django invokes the queryset, it gets stale data either from its own caches (unlikely unless you were reusing querysets, which I didn't see in the portion of the code you posted) or the DB is caching results for the same Django connection. 当django调用queryset时,它会从自己的缓存中获取陈旧的数据(除非您正在重用queryset(除非在您发布的代码部分中没有看到),否则不太可能),或者DB正在为同一Django连接缓存结果。

For example if you were to invoke post processing after the celery task has finished in a completely new django request/view you would probably see the new changes in DB just fine. 例如,如果您在一个全新的Django请求/视图中完成celery任务后调用后处理,则您可能会看到DB中的新更改就好了。 However, since your view was blocked while the task was executing (which defeats the purpose of celery btw) internally django only keeps the snapshot of the DB at the time the view was entered. 但是,由于在执行任务时视图被阻塞(这与celery btw的目的背道而驰),因此内部django仅在进入视图时保留数据库的快照。 Therefore your get fails and you confirmed this behavior directly when simply entering the django shell. 因此,您的获取失败,您仅在进入django shell时就直接确认了此行为。

You can fix this like you already did by either: 您可以通过以下任一方法来解决此问题:

  • invoking transactional management which will refresh the snapshot 调用将刷新快照的事务管理
  • changing on your DB endpoint caching and autocommit policies 更改数据库端点缓存和自动提交策略
  • have celery make a callback to django (web request) once it is done to finalize processing (which is likely what you want to do anyway because blocking django defeats the purpose) 一旦celery完成处理以结束处理(使celery回调到django(Web请求)),无论如何,这都是您想做的,因为阻止django破坏了目标)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM