首页 > 解决方案 > F() 表达式中的 Django 竞争条件聚合(Max)

问题描述

想象以下模型:

class Item(models.Model):
    # natural PK
    increment = models.PositiveIntegerField(_('Increment'), null=True, blank=True, default=None)
    # other fields

创建项目时,我希望increment字段自动获取整个表中的最大值,+1。例如:

|_item____________________________|
|_id_|_increment__________________|
| 1  | 1                          |
| 2  | 2                          |
| 4  | 3                          | -> id 3 was deleted at some stage..
| 5  | 4                          |
| 6  | 5                          |
.. etc

当一个新的Item()进来并且是saved()时,如何在一次通过中,以避免竞争条件的方式,确保它有增量 6 而不是 7,以防另一个进程同时做完全相同的事情?

我努力了:

with transaction.atomic():
    i = Item()
    highest_increment = Item.objects.all().aggregate(Max('increment'))
    i.increment = highest_increment['increment__max']
    i.save()

我希望能够以类似于以下的方式创建它,但这显然不起作用(检查过像https://docs.djangoproject.com/en/3.2/ref/models/expressions/#avoiding这样的地方-race-conditions-using-f):

from django.db.models import Max, F
i = Item(
   increment=F(Max(increment))
)

非常感谢

标签: djangoaggregaterace-condition

解决方案


推荐阅读