2010-07-31 2 views
3

В приложении Django Мне нужно создать номер заказа, который выглядит как: yyyymmddnnnn, в котором гггг = год, мм = месяц, дд = день и нннн это число от 1 до 9999.Django, доступ к последовательности PostgreSQL

Я думал, что могу использовать последовательность 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() 'от Джанго интерактивной оболочки он ведет себя, как ожидалось.

>>> 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. Я понятия не имею, где проблема.

+0

Думаю, нам нужно больше узнать из вашего кода. – KillianDS

+0

В основном код кода отсутствует. Но я изменил свое мнение о том, как создавать номера заказов. Мне нужно было создать уникальные номера заказов, чтобы отслеживать заказы, если это необходимо. И то, как я пытался, имеет серьезный недостаток. Я должен сбросить счетчик каждый день ровно в полночь. В любом случае, все вы, ребята, благодарите за ответ. – Henri

+0

Похоже, что ошибка была в другой части приложения, поэтому проблема решена. Где-то я кое-что прочитал о создании номеров заказов: http://stackoverflow.com/questions/1179439/best-way-to-generate-order-numbers-for-an-online-store и вот некоторые очень полезные советы. – Henri

ответ

3

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

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

Для получения более подробной информации см. Запись «Псевдоэфир» в SQL Antipatterns. (заметьте, это ссылка на книгу, которую полный текст доступен не бесплатно).

Смежные вопросы