我有一些特殊要求,我正在努力找出编码它的最佳方法。 最佳效率最高,可维护性最高。要求是这样的(跟我一起):
我的Django网站上有一个功能,即为 注册和未注册用户提供服务。此功能将在每个用户的引脚代码后面进行门控。我要求这些引脚是随机生成的(而不是连续生成的)。
密码需要令人难忘 - 这意味着密钥len
成为一个因素。因此,我要去一个 4位引脚。还有数字,因为字母数字比纯数字更难忘(根据我进行的可用性测试 - 我坚持这些结果)。
我不能在密码代码之间发生冲突,因为它们也会被用作标识符 - 所以它们都必须是唯一的。我的范围将在0000到9999之间。只有10K的独特组合可能。这是限制性的,但是引脚代码的可记忆性优先于可能的引脚代码池的大小。所以我会牺牲。
最后,将永久分配注册用户的密码。另一方面,未注册的用户将被分配保留不超过24小时的引脚,之后到期 - 因此再次进入未使用的引脚池。
想象一下我上面的数据模型(在models.py
中)是这样的:
class Inbox(models.Model):
pin_code = models.CharField(default='0')
owner = models.ForeignKey(User)
creation_time = models.DateTimeField(auto_now_add=True)
在views.py
中,我需要一种方法为我创建的每个pin_code
对象分配一个可用的Inbox
。什么是最有效的逻辑?以下是我的想法,我可以接近它:
def expire_pin(time_difference=None):
#admin user (with id 1) is assumed as the 'unregistered user'
Inbox.objects.filter(creation_time__lte=time_difference,owner_id=1).update(pin_code='0')
def get_pin():
parent_list = ['{:04d}'.format(i) for i in range(10000)]
day_ago = timezone.now() - timedelta(hours=24)
expire_pin(day_ago)
to_exclude = Inbox.objects.filter(~Q(pin_code='0')).values_list('pin_code',flat=True)
new_list = [item for item in parent_list if item not in to_exclude]
return random.choice(new_list)
可选:您不必阅读它,但这是我正在使用的pin_code
。每个已注册和未注册的用户都会分配一个可在example.com/pin/XXXX
(XXXX
为pin_code
)访问的收件箱。用户可以通过社交媒体与他们的朋友分享此收件箱地址。然后,朋友可以通过他们的移动号码登录它,查看前用户特别为所述朋友的眼睛留下的内容。抓住漂移?
我为已注册和未注册的用户都需要此功能 - 因此需要为{1}}分配给未知用户。但我希望能够回收未注册的用户代码,这样我就不会太快耗尽10K的可能性。我在这个网站上有一个中等大的用户群。
最终,我将用完10K组合。我想我会写代码,然后无缝转换到5位数的引脚。但即使在这种情况下,如果任何4位数的引脚过期并可用,它们将在分配期间获得优先权。如果你也可以帮助我,那就太好了!
答案 0 :(得分:1)
您需要的只是RandomCharField
个django-extensions
包。请参阅django-extensions docs。
RandomCharField(length=4, include_alpha=False)
# 7097
在您的代码中:
from django_extensions.db.fields import RandomCharField
class Inbox(models.Model):
pin_code = RandomCharField(length=4, unique=True, include_alpha=False)
owner = models.ForeignKey(User)
creation_time = models.DateTimeField(auto_now_add=True)
答案 1 :(得分:0)
相当一个故事,但我不是100%确定你的问题是什么。如何生成随机数?
import random
print('%04d' % random.randint(0, 10000))
将其置于while循环中以确保它尚未存在于数据库中。或者,使用used
布尔值在数据库中预生成10000个引脚号的列表,以获得更高效的解决方案。
我不得不问,是否记得真的有要求?如果是,是不是一个自定义字符串更好的主意?随机数字并不容易记住,人们更善于记住他们自己想到的东西。
答案 2 :(得分:0)
用于密码分配;我很相信你的代码做了类似的事情:
首先,我将保留所有代码可能性的列表(现在也可以创建列表),因此将是一个简单的表: 独特-4位代码:分配布尔
然后我会创建一个函数:
sudo代码:
def new_pin(db_list):
# db_list is passed in array of db values where assigned-boolean = false
random number between 1 and 9998 # i wouldn't use 0000 and 9999, may even want to remove all 1111, 2222, but will further reduce pool size
if rand in db_list:
db.assigned-boolean = true for rand
return rand
else:
return new_pin(db_list)
上述问题;你可以有竞争条件,所以必须锁定db_list的数据库表,其他调用必须等到db_list可用,这样你就不会意外地分配一个引脚(不太可能使用rand,但可能发生在足够忙碌的小站点。)
另一种选择是为您的网址添加更多复杂性,例如 example.com/USER_NAME/XXXX
让用户选择XXXX并确保它们具有唯一的名称。对于那些未注册的人,您可以指定一个随机单词。
如果那太复杂了;我建议允许长度为3到6的代码 example.com/pin/XXX example.con /销/ XXXX example.com/pin/XXXXX等
如果分配了引脚,则所有工作。这会大大增加您的游泳池大小。
答案 3 :(得分:0)
如果您改为
,该怎么办?class PinCode(models.Model):
code = models.CharField(max_length='4', primary_key=True, validators=[lambda x: len(x) == 4])
current_owner = models.ForeignKey(User, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
然后获取一个引脚,只需简单地查询PinCodes,查找下一个无主或未到期的PinCodes。