2

現在、models.py で行っていること:

class Customer(models.Model):
    def save(self, *args, **kwargs):
        if self.cod == '':
            self.cod = "CUST%d" % self.id
        super(Customer, self).save(*args, **kwargs)

そして、すべてがうまくいくように見えました。問題は、id AutoField が実際にいくつかの数字をスキップすることです。そのようなシナリオが得られます。

  • CUST1
  • CUST2
  • CUST4
  • CUST5

ご覧のとおり、CUST3 はありません。AutoField はそれをスキップしました。しかし、財務上の理由から、コードはプログレッシブで密集している必要があります。目標を達成するにはどうすればよいですか?ありがとうございました

編集:PostgreSQLを使用しています

4

1 に答える 1

1

こちらにも報告されているように、これは、ギャップレスシーケンスを回避する同時実行とパフォーマンスに関係する DBMS 関連のもののようです。

そこで、行を保持、ロック、インクリメントする補助モデル「プログレッシブ」を使用してその問題を解決しました。

# models.py
from django.db import models, transaction

class Counter(models.Model):
    name = models.CharField(max_length=40, unique=True, db_index=True)
    n = models.PositiveIntegerField(default=1)

class Customer(models.Model):
    def save(self, *args, **kwargs): 
        super(Customer, self).save(*args, **kwargs)

        if self.cod == '':
            with transaction.commit_on_success():
                try:
                    counter = Counter.objects.select_for_update().get(name='Customer')
                except Counter.DoesNotExist:
                    counter = Counter.objects.select_for_update().create(name='Customer')
                self.cod = "CUST%d" % counter.n
                counter.n += 1
                counter.save()
            super(Customer, self).save(*args, **kwargs)

トランザクションが終了しないまで行をロックすることに注意してくださいselect_for_update()(ただし、使用する DBMS に注意してください)。

お役に立てれば

于 2013-07-09T07:58:38.637 に答える