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)
?@ilvarreservation
有一个指向项目的外键,而不是另一种方式这实际上不是真的。只要要引用同一模型上的字段,就可以使用F()表达式。这可以出于各种原因进行,包括比较和更新。我发布的代码应该会导致查询通过预订减少项目.可用
。数量
,而不是获取项目可用
的值并将其插回。但是很明显,我做错了什么,因为它没有达到预期的效果。顺便说一句,“一件物品只能根据上次预订减少”是我面临的问题,而不是要求!它应该根据所有保留减少,除非这些已经按照进行了处理,这正是F()表达式的使用方式之一。文档实际上展示了F()表达式的这种使用方式,作为处理竞争条件的方式,正如问题中所示。看见