Джанго, доступ к последовательности PostgreSQL - PullRequest
4 голосов
/ 01 августа 2010

В приложении Django мне нужно создать номер заказа, который выглядит следующим образом: yyyymmddnnnn, в котором yyyy = год, mm = месяц, dd = день, а 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

теперь, когда я вызываю get_new_order_number () из интерактивной оболочки django, он ведет себя как положено.

>>> 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'

Вы видите числа, постепенно увеличивающиеся на единицу каждый раз, когда вызывается функция.Вы можете запустить несколько интерактивных сессий django, и номера будут постепенно увеличиваться, при этом в разных сессиях не будет идентичных номеров.

Теперь я пытаюсь использовать вызов этой функции из вида:

import get_order_number

order_number = get_order_number.get_new_order_number()

и это дает мне номер.Однако в следующий раз, когда я получаю доступ к представлению, оно увеличивает число на 2. Я понятия не имею, в чем проблема.

1 Ответ

4 голосов
/ 01 августа 2010

Лучшее решение, которое я могу придумать, это: не беспокойтесь, если номера ваших заказов редки. Не должно иметь значения, отсутствует ли номер заказа: нет способа гарантировать, что номера заказов являются смежными, что в какой-то момент не будет зависеть от состояния гонки.

Ваша самая большая проблема, вероятно, заключается в том, чтобы убедить заостренных, что «пропущенные» номера заказов не проблема.

Дополнительные сведения см. В записи Psuedo-Key Neat Freak в SQL Antipatterns . (обратите внимание, это ссылка на книгу, полный текст которой не доступен бесплатно).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...