我有一个带有唯一整数的模型,需要针对外键增加,以下代码是我当前处理它的方式:
class MyModel(models.Model):
business = models.ForeignKey(Business)
number = models.PositiveIntegerField()
spam = models.CharField(max_length=255)
class Meta:
unique_together = (('number', 'business'),)
def save(self, *args, **kwargs):
if self.pk is None: # New instance's only
try:
highest_number = MyModel.objects.filter(business=self.business).order_by('-number').all()[0].number
self.number = highest_number + 1
except ObjectDoesNotExist: # First MyModel instance
self.number = 1
super(MyModel, self).save(*args, **kwargs)
我对此有以下问题:
MyModel
创建business
个实例。 2个人是否可以同时创建MyModel
个实例,而.count()
同时为这两个实例返回500个,然后两个人同时尝试基本设置self.number = 501
(引发IntegrityError)?答案似乎很明显“是的,它可能会发生”,但我不得不问。SuperAutoField
)?我不能只打一个while model_not_saved:
try:
,except IntegrityError:
,因为模型中的其他限制可能导致无限循环,而且比切尔诺贝利更糟糕的灾难(可能不是非常糟糕的。)
答案 0 :(得分:2)
您希望在数据库级别使用该约束。否则你最终会遇到你讨论过的并发问题。解决方案是将整个操作(读取,增量,写入)包装在事务中。
为什么不能使用AutoField代替PositiveIntegerField?
number = models.AutoField()
然而,在这种情况下,数字几乎肯定会等于yourmodel.id
,那么为什么不使用呢?
修改强>
哦,我知道你想要什么。除非有MyModel.business
个实例,否则您希望数字字段不会增加。
如果可以,我仍然建议您只使用id
字段,因为它肯定是唯一的。如果你绝对不想这样做(也许你正在向用户显示这个数字),那么你需要在事务中包装你的save方法。
您可以在文档中阅读有关交易的更多信息:
http://docs.djangoproject.com/en/dev/topics/db/transactions/
如果您只是使用它来计算MyModel有多少FK到Business的实例,那么您应该将其作为查询而不是尝试存储计数。