Django,访问PostgreSQL序列

时间:2010-07-31 21:44:16

标签: django postgresql django-models

在Django应用程序中,我需要创建一个类似于yyyymmddnnnn的订单号,其中yyyy = year,mm = month,dd = day,nnnn是1到9999之间的数字。

我认为我可以使用PostgreSQL序列,因为生成的数字是原子的,所以我可以确定进程得到的数字是唯一的数字。

所以我创建了一个PostgreSQL序列:

CREATE SEQUENCE order_number_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9999
START 1
CACHE 1
CYCLE;

该序列可以作为具有一行的表来访问。所以在文件checkout.py中我创建了一个Django模型来访问这个序列。

class OrderNumberSeq(models.Model):
    """
    This class maps to OrderNumberSeq which is a PostgreSQL sequence.
    This sequence runs from 1 to 9999 after which it restarts (cycles) at 1.
    A sequence is basically a special single row table.
    """
    sequence_name = models.CharField(max_length=128, primary_key=True)
    last_value = models.IntegerField()
    increment_by = models.IntegerField()
    max_value = models.IntegerField()
    min_value = models.IntegerField()
    cache_value = models.IntegerField()
    log_cnt = models.IntegerField()
    is_cycled = models.BooleanField()
    is_called = models.BooleanField()

    class Meta:
        db_table = u'order_number_seq'

我将sequence_name设置为主键,因为Django坚持在表中使用主键。

我创建了一个文件get_order_number.py,内容为:

def get_new_order_number():
    order_number = OrderNumberSeq.objects.raw("select sequence_name, nextval('order_number_seq') from order_number_seq")[0]

    today = datetime.date.today()
    year = u'%4s' % today.year
    month = u'%02i' % today.month
    day = u'%02i' % today.day

    new_number = u'%04i' % order_number.nextval
    return year+month+day+new_number

现在当我从django交互式shell调用'get_new_order_number()'时,它的行为符合预期。

>>> checkout.order_number.get_new_order_number()
u'201007310047'
>>> checkout.order_number.get_new_order_number()
u'201007310048'
>>> checkout.order_number.get_new_order_number()
u'201007310049'

每次调用函数时,您都会看到数字正好递增1。您可以启动多个交互式django会话,并且数字会很好地增加,而不同会话中不会出现相同的数字。

现在我尝试从视图中调用此函数,如下所示:

import get_order_number

order_number = get_order_number.get_new_order_number()

它给了我一个数字。但是,下次我访问视图时,它会将数字增加2.我不知道问题出在哪里。

1 个答案:

答案 0 :(得分:4)

我能想出的最佳解决方案是:如果您的订单数量稀少,请不要担心。如果订单号丢失则无关紧要:没有办法确保订单号是连续的,在某些时候不会受到竞争条件的影响。

你最大的问题可能是说服那些尖头发的人,说“错过”订单号不是问题。

有关详细信息,请参阅SQL Antipatterns中的Psuedo-Key Neat Freak条目。 (注意,这是一本书的链接,其全文不是免费提供的。)