Создание django возражает со случайным первичным ключом

Я работаю с API, который хочет, чтобы я генерировал непрозрачные "ссылочные идентификаторы" для транзакций с их API, другими словами, уникальные ссылки, которые пользователи не могут предположить или вывести всегда. ('выводят' надлежащий английский язык?)

Это - то, что я взламывал вместе в настоящее время:

randomRef = randint(0, 99999999999999)
while Transaction.objects.filter(transactionRef = randomRef).count():
    randomRef = randint(0, 99999999999999)

Transaction.objects.create(user=user, transactionRef=randomRef, price=999)

к сожалению, моя база данных, кажется, пропускает транзакции в данный момент. Я понял, что мой метод не особенно ориентирован на многопотоковое исполнение (скажите, что я выполняю тот же код django нескольких mod_wsgi апачских потоков, они могли все генерировать тот же randomRef!)

Кто-либо заставил более хороший прием генерировать случайные первичные ключи для меня?

9
задан rdrey 23 September 2014 в 11:24
поделиться

4 ответа

Почему бы вместо этого просто не зашифровать обычные последовательные идентификаторы? Для того, кто не знает ключа шифрования, идентификаторы будут казаться такими же случайными. Можно написать обертку, которая автоматически расшифровывает идентификатор на пути к БД и шифрует его на пути из БД.

16
ответ дан 4 December 2019 в 06:22
поделиться

Случайные целые числа не уникальны, и первичные ключи должны быть уникальными. Сделайте ключевое поле символом (32) и попробуйте следующее:

from uuid import uuid4 as uuid
randomRef = uuid().hex

UUID очень хороши для обеспечения уникальности.

2
ответ дан 4 December 2019 в 06:22
поделиться

Вы должны иметь возможность сделать столбец transactionRef в своей базе данных уникальным. Таким образом, база данных не позволит добавлять транзакции с тем же значением transactionRef. Одна из возможностей - случайным образом сгенерировать UUID - вероятность столкновения случайных UUID чрезвычайно мала.

2
ответ дан 4 December 2019 в 06:22
поделиться

os.urandom (n) может «вернуть строку из n случайных байтов, подходящую для криптографического использования». Просто убедитесь, что n достаточно велико, чтобы 2 ** (8 * n) было намного выше квадрата количества "уникальных" ключей, которые вы хотите идентифицировать, и вы можете максимально снизить риск столкновения. Например, если вы думаете, что в итоге у вас может быть миллиард транзакций (около 2 ** 30 ), n = 8 может быть достаточно (но не рискуйте и используйте несколько больший n в любом случае ;-).

2
ответ дан 4 December 2019 в 06:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: