我正在 Django 模型中实现一个字段,它调用以下函数作为默认值
def get_default_value():
a = MyModel.objects.aggregate(max_id=Max('id'))
return get_unique_value_based_on_num(a['max_id'] or 0)
class MyModel:
default_value_field = CharField(default=get_default_value)
虽然我在这方面可能是错的,但我担心这个实现可能会导致竞争条件。
有更好的方法吗?可能使用 F 对象或其他东西?
最佳答案
为避免竞争条件,最好让数据库处理表的完整性,这是数据库的目的之一。
为此,请捕获通过保存模型实例引发的任何 IntegrityError
,并在失败时使用不同的值重试。
from django.db import IntegrityError, models, transaction
def get_default_value():
a = MyModel.objects.aggregate(max_id=Max('id'))
return get_unique_value_based_on_num(a['max_id'] or 0)
class MyModel(models.Model):
# Have unicity enforced at database level with unique=True.
default_value_field = models.CharField(max_length=200, unique=True)
def save(self):
if not self.default_value_field:
max_tries = 100 # Choose a sensible value!
for i in range(max_tries):
try:
self.default_value_field = get_default_value()
# Atomic block to rollback transaction in case of IntegrityError.
with transaction.atomic():
super(MyModel, self).save()
break
except IntegrityError:
# default_value_field is not unique, try again with a new value.
continue
else:
# Max tries reached, raise.
raise IntegrityError('Could not save model because etc...')
else:
super(MyModel, self).save(*args, **kwargs)
关于python - 在 Django 模型字段中设置默认值的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29804593/