如果对象已在Django中删除,如何更新或保释

mga*_*lgs 5 python django locking celery database-locking

我有一个Django应用程序,将对象保存到数据库中,还有一个芹菜任务,该任务定期对其中一些对象进行一些处理。问题在于,在芹菜任务已选择要处理的对象之后,但芹菜任务实际完成处理并保存之前,用户可以删除对象。因此,当celery任务确实调用时.save(),即使用户删除了该对象,该对象也会重新出现在数据库中。当然,这对于用户来说确实很诡异。

所以这是一些显示问题的代码:

def my_delete_view(request, pk):
    thing = Thing.objects.get(pk=pk)
    thing.delete()
    return HttpResponseRedirect('yay')

@app.task
def my_periodic_task():
    things = get_things_for_processing()
    # if the delete happens anywhere between here and the .save(), we're hosed
    for thing in things:
        process_thing(thing) # could take a LONG time
        thing.save()
Run Code Online (Sandbox Code Playgroud)

我考虑过尝试通过添加原子块和事务来修复它,然后在保存对象之前测试该对象是否确实存在,以进行修复:

@app.task
def my_periodic_task():
    things = Thing.objects.filter(...some criteria...)
    for thing in things:
        process_thing(thing) # could take a LONG time
        try:
            with transaction.atomic():
                # just see if it still exists:
                unused = Thing.objects.select_for_update().get(pk=thing.pk)
                # no exception means it exists. go ahead and save the
                # processed version that has all of our updates.
                thing.save()
         except Thing.DoesNotExist:
             logger.warning("Processed thing vanished")
Run Code Online (Sandbox Code Playgroud)

这是做这种事情的正确模式吗?我的意思是,我将在生产中运行它几天之内找出它是否可以工作,但是很高兴知道是否还有其他公认的模式可以完成这种事情。

我真正想要的是能够更新数据库中仍然存在的对象。我可以接受用户编辑与进行的编辑之间的竞争process_thing,而且我总是可以在refresh_from_db之前加入,process_thing以最大程度地减少丢失用户编辑的时间。但是我绝对不能在用户删除对象后使它们重新出现。

mga*_*lgs 0

目前看来,“再次原子选择,然后保存”的模式就足够了:

@app.task
def my_periodic_task():
    things = Thing.objects.filter(...some criteria...)
    for thing in things:
        process_thing(thing) # could take a LONG time
        try:
            with transaction.atomic():
                # just see if it still exists:
                unused = Thing.objects.select_for_update().get(pk=thing.pk)
                # no exception means it exists. go ahead and save the
                # processed version that has all of our updates.
                thing.save()
         except Thing.DoesNotExist:
             logger.warning("Processed thing vanished")
Run Code Online (Sandbox Code Playgroud)

(这与我原来的问题中的代码相同)。