如何为多个模型提供连续的 ID?

Posted

技术标签:

【中文标题】如何为多个模型提供连续的 ID?【英文标题】:How to have continuous ids for multiple models? 【发布时间】:2017-10-01 13:32:35 【问题描述】:

我编写了自己的计费软件,但我不知道如何解决这个问题。

现在我有 3 个模型:

号码 收据 里程收据

关键是我需要给我的客户写两种收据。但是对于财政部来说,他们必须有一个连续的ID。所以 Number 只包含一个自动字段,而 Receipt 和 MilageReceipt 只包含一个外键。这样我就有了两个不同模型的 ID。

但现在我想扩展它以处理多家公司。所以有两种不同类型的 Receipts 需要有连续编号,但是会有多个用户都需要自己的连续编号。

我想要一些结果: 收据:公司:1,身份证:1 收据:公司:2,身份证:1 收据:公司:1,身份证:2 里程收据:公司:1,id:3 收据:公司:2,身份证:2 里程收据:公司:1,id:4 收据:公司:1,身份证:5 里程收据:公司:2,id:3

我希望有点清楚我想要实现的目标。能否请您指出如何设置模型以实现此行为的方向?

我想尽可能保持管理员的原创性,所以我想在模型级别而不是视图上执行此操作 - 如果可能的话。例如,现在,每次创建收据或 MilageReceipt 时,我都会自动创建数字。所以用户甚至都不会注意到。

感谢您的帮助!

【问题讨论】:

【参考方案1】:

对于连续序列,你真的不能使用数据库序列。最简单的解决方案是拥有自己的表(模型)来保存序列。这是我用来执行此操作的一些代码:

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() 方法中。

【讨论】:

以上是关于如何为多个模型提供连续的 ID?的主要内容,如果未能解决你的问题,请参考以下文章

如何为单个模型保存多个单独的记录

如何为模板重用 Kendo UI 组件?属性“.name”为多个 HTML 元素在 DOM 中提供完全相同的 ID

如何为 MFC 中的多个按钮编写一个消息处理程序?

在 Anylogic 中,我如何为向多个客户交付订单的卡车建模

如何为多个模型使用 tensorflow 服务

如何为模型设置多个作者类型