rdr*_*rey 9 python random django primary-key
我正在使用一个API,它希望我为使用API的事务生成不透明的"引用ID",换句话说,用户无法以任何方式猜测或推断的唯一引用.(是'推断'适当的英语?)
这就是我目前一起入侵的内容:
randomRef = randint(0, 99999999999999)
while Transaction.objects.filter(transactionRef = randomRef).count():
randomRef = randint(0, 99999999999999)
Transaction.objects.create(user=user, transactionRef=randomRef, price=999)
Run Code Online (Sandbox Code Playgroud)
不幸的是,我的数据库目前似乎缺少交易.我已经意识到我的方法并不特别是线程安全(假设我在多个mod_wsgi apache线程上运行相同的django代码,它们都可以生成相同的randomRef!)
有没有人有更好的技巧为我生成随机主键?
Tre*_*ner 11
我根据这个问题创建了一个要点:https://gist.github.com/735861
根据Amber的建议,使用DES对私钥进行加密和解密.加密密钥在基数36中表示,但只要表示是唯一的,任何其他基于字符的表示都将起作用.
任何需要这种加密私钥表示的模型只需要继承代码中显示的模型和管理器.
这是代码的内容:
import struct
from Crypto.Cipher import DES
from django.db import models
class EncryptedPKModelManager(models.Manager):
"""Allows models to be identified based on their encrypted_pk value."""
def get(self, *args, **kwargs):
encrypted_pk = kwargs.pop('encrypted_pk', None)
if encrypted_pk:
kwargs['pk'] = struct.unpack('<Q', self.model.encryption.decrypt(
struct.pack('<Q', encrypted_pk)
))[0]
return super(EncryptedPKModelManager, self).get(*args, **kwargs)
class EncryptedPKModel(models.Model):
"""Adds encrypted_pk property to children."""
encryption = DES.new('8charkey') # Change this 8 character secret key
def _encrypted_pk(self):
return struct.unpack('<Q', self.encryption_obj.encrypt(
str(struct.pack('<Q', self.pk))
))[0]
encrypted_pk = property(_encrypted_pk)
class Meta:
abstract = True
Run Code Online (Sandbox Code Playgroud)
对于Transaction调用的对象transaction,transaction.encrypted_pk将返回私钥的加密表示. Transaction.objects.get(encrypted_pk=some_value)将基于加密的私钥表示来搜索对象.
应该注意的是,此代码假定仅适用于可以正确表示为长值的私钥.