我的模型有一个默认为随机生成的字符串的CharField
,该字符串应该是唯一的。我不想使用UUIDField
.如果生成的代码是重复的,有没有办法覆盖保存方法来处理引发IntegrityError
?还是我应该在我的生成函数中检查这一点?
型
class Item(models.Model):
...
item_code = models.CharField(max_length=11, default=get_generated_code, unique=True)
功能
def get_generated_code():
code = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(11))
return code
这就是我最终所做的。
我覆盖了 save 方法,以便在其中设置代码并检查完整性错误,这仅在 3 次尝试失败后才会引发它。由于发生冲突的可能性足够小,尤其是在连续 3 次尝试之后,我觉得这是一个足够的解决方案,而不是在替代解决方案中进行多个数据库查询。
class Item(models.Model):
...
# blank = True as this is handled by save method
code = models.CharField(max_length=11, blank=True, unique=True)
def save(self, *args, **kwargs):
if not self.code:
self.code = get_generated_code()
success = False
errors = 0
while not success:
try:
super(Item, self).save(*args, **kwargs)
except IntegrityError:
errors += 1
if errors > 3:
# tried 3 times, no dice. raise the integrity error and handle elsewhere
raise
else:
self.code = get_generated_code()
else:
success = True
考虑用
原子事务包装super
方法以避免任何TransactionManagementError
。
from django.db import IntegrityError, transaction
def save(self, *args, **kwargs):
try:
with transaction.atomic():
super(Keyword, self).save(*args, **kwargs)
except IntegrityError:
# [...] do something else
raise IntegrityError