【问题标题】:How to have continuous ids for multiple models?如何为多个模型提供连续的 ID?
【发布时间】: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 时,我都会自动创建数字。所以用户甚至都不会注意到。

感谢您的帮助!

【问题讨论】:

    标签: python django database django-models models


    【解决方案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() 方法中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      • 2022-11-03
      • 2019-04-19
      • 1970-01-01
      • 2015-07-01
      • 2016-03-21
      • 2021-10-06
      相关资源
      最近更新 更多