如何在Django中检查是否达到最大db条目数,如果达到最大db条目数,如何回滚?

如何在Django中检查是否达到最大db条目数,如果达到最大db条目数,如何回滚?,django,Django,我想检查是否达到db条目的最大值=已预订。对于Django 1.5,我使用了如下内容: @transaction.commit_on_success def save(self, *args, **kwargs): super(MyModel, self).save(*args, **kwargs) if MyModel.objects.all().count() > max: raise ValidationError('It was just fully

我想检查是否达到db条目的最大值=已预订。对于Django 1.5,我使用了如下内容:

@transaction.commit_on_success
def save(self, *args, **kwargs):
    super(MyModel, self).save(*args, **kwargs)
    if MyModel.objects.all().count() > max:
        raise ValidationError('It was just fully booked.')
我不知道这是不是胡说八道。无论如何,我无法在新transaction.atomic块中执行查询MyModel.objects.count。我收到错误TransactionManagementError:当前事务中发生错误。在“原子”块结束之前,无法执行查询。。假设:如果您试图在回滚发生之前运行数据库查询,Django将引发TransactionManagementError

达到目标的最佳实践是什么?这个问题有没有特别的术语


背景:我想当几个用户同时创建MyModel对象时,当几乎达到max时,我在db中的条目比max允许的多。因此,我认为保存后也检查一下是个好主意。

可能有几种方法可以实现您想要的。这取决于数据库的使用方式

如果只有一个单线程web服务器访问您的数据库,则上述方法将起作用。最好不要使用save方法,而是覆盖模型上的clean方法:

def clean(self):
    # make sure that user and group are in the same company
    if MyModel.objects.all().count() > max:
        raise ValidationError(
            'All booked out'
        )
但是,如果可能有多个服务器或线程运行上述代码,您将遇到麻烦。假设你的最大值是10。您的数据库当前包含9个条目。两台服务器同时运行上述代码,并且它通过了,就像在每种情况下一样,没有达到max。每个都写入数据库,现在您有11个条目

这是有办法的。您可以创建一个名为EntryCount的新模型。让它只包含一行,其中包含一个数值。这是条目的计数。该列上还有一个DB约束,表示其最大值为10。您的save方法需要被重写以增加这个数字。如果试图使数字大于10,则会引发错误


这种替代方法的原因是count*的工作方式非常奇怪。隔离级别可能会使不同的DB连接看起来有所不同

让您知道:您不必在count之前调用all来计算所有模型对象,只需执行MyModel.objects.count您所说的我不能执行查询是什么意思?当你这样做时会发生什么?此外,在默认事务隔离级别下,此方案不会实现您想要的功能。如果您使用SERIALIZABLE,它应该可以工作,但是您需要检查特定于数据库的文档。您还可以获取一个表锁。在save方法上,您不需要@transaction.commit\u on\u success;你也在检查前先存钱,所以这不是你所想的。@kevinchristopherhhenry。我更新了我的问题,但产生错误的代码更复杂。我很快阅读了PostgreSQL文档中关于serialisable的内容…我需要一段时间才能理解它。您关于并发读取问题的场景是正确的。但是,您的解决方案将出现相同的问题,除非代码设计为在读取EntryCount的单行时获得写锁。这通常是通过选择用于更新的\u来完成的。我不同意“计数”以微妙的奇怪方式工作的观点。它的工作方式没有任何微妙或奇怪之处。@Louis这意味着用try:counter=EntryCount.objects子类化我的save方法是一个很好的解决方案;计数器计数+=1;counter.save;超级模型,self.save*args,**kwargs;除了:…@Louis有点奇怪,我明白我在含糊其辞。根据我对各种数据库管理系统的经验,我有一种恐惧感。在获得完整计数之前,不同的表需要不同的锁。我不记得细节,但我不会依赖于多线程环境中的count*行为,除非我对我使用的特定DBMS进行了具体的研究和测试。当然,行为在每个DBMS中都有很好的定义。然而,我发现它的工作方式令人惊讶,以微妙的奇怪方式:我接受这个答案和路易斯的第一个评论。多亏了这两个!