2017-05-03 29 views
-2

我寫了自己的計費軟件,但我不知道如何解決這個問題。如何爲多個模型創建連續的ID?

現在,我有3種型號:

數 收據 MilageReceipt

的一點是,我需要2種收據寫信給我的costumers。但對於財政部來說,他們必須持續有一個身份證。所以Number只包含一個自動字段,而Receipt和MilageReceipt只有一個外鍵。這樣我有兩個不同型號的ID。

但現在我想擴大這個也處理多個公司。因此,有兩種不同類型的收據需要連續編號,但會有多個用戶需要自己的連續編號。

我想要的東西,其結果是: 回執:公司:1,ID:1個 回執:公司:2,ID:1個 回執:公司:1,ID:2 MilageReceipt:公司:1, ID:3 收據:公司:2,ID:2 MilageReceipt:公司:1,ID:4 收據:公司:1,ID:5 MilageReceipt:公司:2,ID:3

我希望它有點清楚我想達到什麼。你能指點我如何建立模型來獲得這種行爲嗎?

我想保持管理員儘可能原創,所以我想在模型層面上做到這一點,而不是視圖 - 如果可能的話。例如,我現在每次創建Receipt或MilageReceipt時都會自動創建Number。所以用戶甚至沒有注意到。

謝謝你的幫助!

回答

0

對於連續序列,你真的不能使用數據庫序列。最簡單的解決方案是擁有自己的表格(Model)來保存序列。下面是一些代碼,我用它來做到這一點:

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) 

由於每家公司都將有一個不同的密鑰,他們將是不同的序列。

如果你在使用這個假設你的收據保存方法,像這樣:

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