Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python/Django中生成唯一的字符串_Python_Django - Fatal编程技术网

在Python/Django中生成唯一的字符串

在Python/Django中生成唯一的字符串,python,django,Python,Django,我想要的是在我的网站上为我的用户生成一个大小为5的字符串(键)。更像是一个BBM别针 该键将包含数字和大写英文字母: AU1B7 Y56AX M0K7A 即使我生成了数百万个字符串,我又怎么能对字符串的唯一性感到放心呢 以最具python风格的方式,我如何做到这一点?我不确定是否有任何简短的神秘方式,但可以使用简单的直接函数实现,假设您将生成的所有字符串保存在一个集合中: import random def generate(unique): chars = "ABCDEFGHIJ

我想要的是在我的网站上为我的用户生成一个大小为5的字符串(键)。更像是一个BBM别针

该键将包含数字和大写英文字母:

  • AU1B7
  • Y56AX
  • M0K7A
即使我生成了数百万个字符串,我又怎么能对字符串的唯一性感到放心呢


以最具python风格的方式,我如何做到这一点?

我不确定是否有任何简短的神秘方式,但可以使用简单的直接函数实现,假设您将生成的所有字符串保存在一个集合中:

import random

def generate(unique):
    chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
    while True:
        value = "".join(random.choice(chars) for _ in range(5))
        if value not in unique:
            unique.add(value)
            break

unique = set()
for _ in range(10):
    generate(unique)
我最喜欢的是

import uuid 
uuid.uuid4().hex[:6].upper()
如果使用django,可以在此字段上设置唯一约束,以确保其唯一

这将生成一些短代码,但它们可以复制。因此,在保存之前,请检查它们在数据库中是否唯一

def generate(size=5):
    code = ''.join(random.choice(string.letters[26:] + string.digits) for in range(size))
    if check_if_duplicate(code):
        return generate(size=5)
    return code

或者使用django unique约束,并处理异常

从3.6开始,您可以使用secrets模块生成漂亮的随机字符串。


如果你能承受在生成的数字中丢失“8”和“9”,那么有一个非常好的办法来获得一个真正的随机数

导入操作系统
导入base64
base64.b32编码(os.uradom(3))[:5]。解码('utf-8')
由于您追求的是唯一性,因此您遇到了一个问题,因为
36*36*36*36*36=60'466'176
,如果您有数百万,这肯定会导致冲突。因为集合比听写快,所以我们

some_dict = set()

def generate():
    return base64.b32encode(os.urandom(3))[:5].decode('utf-8')

def generate_unique():
    string = generate()
    while string not in some_set:
        string = generate()
    some_set.add(string)
    return string

django中有一个函数可以完成您所需的功能(归功于):

Django提供函数
get\u random\u string()
,该函数将满足 字母数字字符串生成要求。你不需要任何东西 额外的包,因为它位于
django.utils.crypto
模块中

>>> from django.utils.crypto import get_random_string
>>> unique_id = get_random_string(length=32)
>>> unique_id
u'rRXVe68NO7m3mHoBS488KdHaqQPD6Ofv'
您还可以使用
允许的字符改变字符集:

>>> short_genome = get_random_string(length=32, allowed_chars='ACTG')
>>> short_genome
u'CCCAAAAGTACGTCCGGCATTTGTCCACCCCT'

在我的许多模型中,我有一个唯一的字段,名为“systemCode”。我是手动生成的,但有时它也可以从用户输入中获取值,所以我必须在保存之前检查这个值,如果它匹配,将这个值重新生成为唯一值

这就是我在这个场景中生成唯一字符串的方式:


这是我的标准课堂模型:

我正在使用save()方法生成并检查此系统代码是否唯一:

但我在所有模型中都有相同的系统代码字段。所以我使用一个函数来生成值

因此,以下是如何使用saveSystemCode()函数为所有模型生成唯一值:



saveSystemCode”函数中的循环阻止再次保存相同的值。

一种更安全、更短的方法是使用Django的加密模块

从django.utils.crypto导入get\u random\u字符串
代码=获取随机字符串(5)
get\u random\u string()
函数返回安全生成的随机字符串,使用
机密
机罩下的模块

您还可以传递
允许的\u字符

>>> short_genome = get_random_string(length=32, allowed_chars='ACTG')
>>> short_genome
u'CCCAAAAGTACGTCCGGCATTTGTCCACCCCT'
从django.utils.crypto导入get\u random\u字符串
导入字符串
code=get\u random\u string(5,允许的字符=string.ascii\u大写+string.digits)

要生成唯一的,可以使用以下命令:

import uuid 
str(uuid.uuid1())[:5]

如果您有一种将每个用户关联到唯一ID的方法(例如Django或Flask中的
主键
)。您可以这样做:

注意:这不会生成固定长度

我们将把
用户id
放到右边,使生成的长度有点静态

import os
import base64

user_id = 1

#pad the string
number_generate = str(user_id).rjust(5,"0")

base64.b32encode(bytes(number_generate, 'utf-8')).decode('utf-8').replace('=','')

base64.b32encode('12345')=='GEZDGNBV'
se您还可以使用
django.utils.crypto.get_random_string(5,string.ascii_大写+string.digits)
生成它们。您可能希望限制字符集,这样就不会生成潜在的混淆字符串,例如
l1I1l
,这些字符串在某些字体中可能无法识别。唯一性要求您持久化分配的字符串集。您不能同时具有“随机”和“唯一”。把“随机”换成“随机看”。因为我是梦想的破碎者,是悲伤和绝望的使者。悲哀和绝望。代码长度+1。但我很好奇你是如何确定你正在创造独特的价值的?它不会生成重复的值吗?当然会有冲突!uuid越长,碰撞的可能性越小。基本上,它需要一些进一步的逻辑,因为所有这些都取决于如何生成和存储它们。这不会生成AU1B7、Y56AX或M0K7A,因为字母字符仅限于A..F。它也不会生成保证唯一的值。您可以添加代码来显示如何处理冲突。您可以像这样处理冲突并生成十六进制字符串。从字面上说,你不能用它创造数百万(复数)。但是你可以生成一百万个。你能澄清一下什么是
string.letters
string.digits
?他的意思是
string.ascii\u letters
,只是为了强调python的
secret
中说明了这一点:“特别是,在random模块中,应该优先使用机密,而不是默认的伪随机数生成器,它是为建模和模拟而设计的,而不是为安全或加密而设计的。”Upvote支持使用python集来收集唯一元素。这会生成一个十六进制字符串。您实际上无法生成数百万(复数)有了它,你可以创造一百万。
    def save(self, *args, **kwargs):
        systemCode = self.systemCode
        if not systemCode:
            systemCode = uuid.uuid4().hex[:6].upper()
        while ClassOne.objects.filter(systemCode=systemCode).exclude(pk=self.pk).exists():
            systemCode = uuid.uuid4().hex[:6].upper()
        self.systemCode = systemCode
        super(ClassOne, self).save(*args, **kwargs)
import uuid 

def saveSystemCode(inClass, inCode, inPK, prefix):
    systemCode = inCode
    if not systemCode:
        systemCode = uuid.uuid4().hex[:6].upper()

    while inClass.objects.filter(systemCode=systemCode).exclude(pk=inPK).exists():
        systemCode = uuid.uuid4().hex[:6].upper()

    return systemCode

class ClassOne(models.Model):
    name = models.CharField(max_length=100)
    systemCode = models.CharField(max_length=25, blank=True, null=True, unique=True)
    ....

    def save(self, *args, **kwargs):
        self.systemCode = saveSystemCode(ClassOne, self.systemCode, self.pk, 'one_')
        super(ClassOne, self).save(*args, **kwargs)


class ClassTwo(models.Model):
    name = models.CharField(max_length=100)
    systemCode = models.CharField(max_length=25, blank=True, null=True, unique=True)
    ....

    def save(self, *args, **kwargs):
        self.systemCode = saveSystemCode(ClassTwo, self.systemCode, self.pk, 'two_')
        super(ClassTwo, self).save(*args, **kwargs)

class ClassThree(models.Model):
    name = models.CharField(max_length=100)
    systemCode = models.CharField(max_length=25, blank=True, null=True, unique=True)
    ....

    def save(self, *args, **kwargs):
        self.systemCode = saveSystemCode(ClassThree, self.systemCode, self.pk, 'three_')
        super(ClassThree, self).save(*args, **kwargs)
import uuid 
str(uuid.uuid1())[:5]
import os
import base64

user_id = 1

#pad the string
number_generate = str(user_id).rjust(5,"0")

base64.b32encode(bytes(number_generate, 'utf-8')).decode('utf-8').replace('=','')