我即将开始开发新的网络应用程序。其中一部分将为用户提供可以以一对多关系进行自定义的页面。这些页面自然需要有唯一的 URL。
留给自己的设备,Django 通常会分配一个标准AUTOINCREMENT
模型的 ID。虽然这效果非常好,但看起来不太好,而且还使页面非常可预测(在本例中这是不需要的)。
我想要的是设定长度、随机生成的字母数字字符串(例如 h2esj4),而不是 1、2、3、4。一组可能的 36 个字符中的 6 个位置应该会给我超过 20 亿个组合,这在这个阶段应该是绰绰有余的。当然,如果以后能扩展一下,那就太好了。
但有两个问题:
随机字符串偶尔会拼出坏词或其他令人反感的短语。有没有一个好的方法来回避这个问题?公平地说,我可能会选择数字字符串,但它确实对冲突的可能性有很大影响。
如何让 Django(或数据库)完成插入方面的繁重工作?我宁愿不插入和then找出关键(因为这不会是一个关键)。我认为如果同时生成两个新页面并且第二个页面(尽管困难重重)在提交第一个页面之前神奇地获得与第一个页面相同的密钥,那么也需要注意并发问题。
我认为这与 URL 缩短器生成 ID 的方式没有一百万英里的不同。如果有一个像样的 Django 实现,我可以利用它。
有内置的 Django 方法来实现你想要的。将字段添加到“自定义页面”模型中primary_key=True
and default=
密钥生成函数的名称,如下所示:
class CustomPage(models.Model):
...
mykey = models.CharField(max_length=6, primary_key=True, default=pkgen)
...
现在,对于每个模型实例page
, page.pk
成为别名page.mykey
,它会自动分配给函数返回的字符串pkgen()
在创建该实例的那一刻。
快速&肮脏的实施:
def pkgen():
from base64 import b32encode
from hashlib import sha1
from random import random
rude = ('lol',)
bad_pk = True
while bad_pk:
pk = b32encode(sha1(str(random())).digest()).lower()[:6]
bad_pk = False
for rw in rude:
if pk.find(rw) >= 0: bad_pk = True
return pk
两个页面获得相同主键的概率非常低(假设random()
足够随机),并且不存在并发问题。当然,通过从编码字符串中切片更多字符,可以轻松扩展此方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)