对于连续序列,你真的不能使用数据库序列。最简单的解决方案是拥有自己的表(模型)来保存序列。这是我用来执行此操作的一些代码:
class Sequence(models.Model):
class Meta:
verbose_name = 'Sequence'
permissions = (('view_sequence', 'Can View Sequence'),)
name = models.CharField(max_length=20)
value = models.IntegerField()
def __str__(self):
return 'Sequence %s=%s' % (self.name, self.value)
def __unicode__(self):
return self.__str__()
@classmethod
def set(cls, name, value=None, increment=0):
with transaction.atomic():
seq = cls.objects.select_for_update().filter(name=name).first()
if not seq:
seq = cls(name=name, value=0)
seq.value = increment + (value if value is not None else seq.value)
seq.save()
return seq.value
@classmethod
def get_next(cls, name):
return cls.set(name, increment=1)
要获得下一个序列,您将形成一个命名序列的键字符串,例如:
nextnumber = Sequence.get_next('receipt_%d' % company.pk)
由于每家公司都有不同的密钥,它们将是单独的序列。
如果你要在假设你的 Receipt 保存方法中使用它,像这样:
class Receipt(models.Model):
def save(self, *args, **kwargs):
if not self.seq_num:
self.seq_num = Sequence.get_next('receipt_%d' % self.company.pk)
super(Receipt, self).save(*args, **kwargs)
company = models.ForeignKey(Company, null=False, Blank=False)
seq_num = models.IntegerField(blank=True, unique=True)
# etc etc
每当您保存收据时,如果它没有 seq_num,则会为其分配一个。
这里只有一个问题,即事务代码的结构方式,如果出现问题,可能会跳过一个数字。为避免这种情况,请将 transaction.atomic() 块移动到您的收据 save() 方法中。