有例子模型:
class MyModel(models.Model):
name = models.CharField()
version = models.IntegerField()
我需要根据同名实例的最大版本设置version
字段值。要做到这一点,我重写save
方法:
def save(self, *args, **kwargs):
max_version = MyModel.objects \
.filter(name=self.name) \
.aggregate(max_version=Max('version'))['max_version'] or 0
self.version = max_version + 1
super(MyModel, self).save(*args, **kwargs)
如何避免竞争条件吗?
编辑:版本必须是唯一的(同名实例之间),但为了不是太重要。
我认为,一个简单的原子transaction应该解决您的问题。
from django.db import transaction
def save(self, *args, **kwargs):
with transaction.atomic():
max_version = MyModel.objects \
.filter(name=self.name) \
.aggregate(max_version=Max('version'))['max_version'] or 0
self.version = max_version + 1
super(MyModel, self).save(*args, **kwargs)
虽然出实际问题的范围,您可能希望只在创建记录(保存的第一次)来更新version
领域。你可以做到这一点通过验证pk
是None
这样。
from django.db import transaction
def save(self, *args, **kwargs):
if self.pk is None:
with transaction.atomic():
max_version = MyModel.objects \
.filter(name=self.name) \
.aggregate(max_version=Max('version'))['max_version'] or 0
self.version = max_version + 1
super(MyModel, self).save(*args, **kwargs)
else:
super(MyModel, self).save(*args, **kwargs)