Python Django-使用F()表达式但获得非原子更新

Python Django-使用F()表达式但获得非原子更新,python,django,django-models,race-condition,Python,Django,Django Models,Race Condition,我有一个如下的管理操作: def process(modeladmin, request, queryset): for reservation in queryset: if not reservation.processed: reservation.processed = True reservation.save() item = reservation.item it

我有一个如下的管理操作:

def process(modeladmin, request, queryset):
    for reservation in queryset:
        if not reservation.processed:
            reservation.processed = True
            reservation.save()
            item = reservation.item
            item.available = F('available') - reservation.quantity
            item.save()
因此,管理员可以处理
项目的
预订
。每当他这样做时,
预订
被标记为已处理,可用的
项目
的数量将减少
预订
中指定的数量

与所有管理操作一样,管理员可以一次处理多个
预订。如果
预订
有所有不同的
项目
,一切都会顺利进行。但如果两个
预订
共享一个
项目
,可用
项目
的数量只会减少上次
预订
处理中指定的数量

我认为
F()
表达式仅适用于这种情况:我想对
item
进行许多更改,并让它们增加或减少
item
上的属性,而不会遇到竞争条件。我缺少什么?

F()表达式用于查询中,例如,当您想在SQL中执行此操作时:

SELECT * FROM foo WHERE foo_col = bar_col
你会:

Foo.objects.filter(foo_col=F('bar_col'))

无论如何,你要求一个项目只能根据最后一次预订减少,这意味着你必须对如何循环预订有点创意。一个选项是按项目id订购queryset,每次id“更改”时,根据该项目的上次预订调整可用金额。

这不是使用F对象的方式。一旦将获取和保存的步骤分开,本质上就是使其显式地非原子化

为此,您应该使用
update
,因此项目部分应为:

Item.objects.filter(id=reservation.item.id).update(available=F('available')-reservation.quantity)

或者类似的东西。

您是如何检测到这一点的?请记住,您必须调用get()来获取新值…我正在查看item.available的值,在处理预订后,该值在管理员中可用!:-)项目是否在预订查询集中获得
select\u related
?为什么不
Item.objects.filter(预订=预订)。update(F('available')-reservation.quantity)
?@ilvar
reservation
有一个指向
项目的外键,而不是另一种方式这实际上不是真的。只要要引用同一模型上的字段,就可以使用F()表达式。这可以出于各种原因进行,包括比较和更新。我发布的代码应该会导致查询通过
预订减少
项目.可用
。数量
,而不是获取
项目可用
的值并将其插回。但是很明显,我做错了什么,因为它没有达到预期的效果。顺便说一句,“一件物品只能根据上次预订减少”是我面临的问题,而不是要求!它应该根据所有保留减少,除非这些已经按照进行了处理,这正是F()表达式的使用方式之一。文档实际上展示了F()表达式的这种使用方式,作为处理竞争条件的方式,正如问题中所示。看见