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

时间:2014-09-25 04:56:18

标签: python django

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

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

  • AU1B7
  • Y56AX
  • M0K7A

即使我以数百万为单位生成字符串,我怎么能对字符串的唯一性保持静止呢?

以最蟒蛇的方式,我该怎么做?

11 个答案:

答案 0 :(得分:25)

我最喜欢的是

import uuid 
uuid.uuid4().hex[:6].upper()

如果您使用django,您可以在此字段上设置唯一约束,以确保它是唯一的。 https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.Field.unique

答案 1 :(得分:4)

一种更安全,更短的方式是使用Django的加密模块。

from django.utils.crypto import get_random_string
code = get_random_string(5)

get_random_string()函数返回安全生成的随机字符串,使用 secrets模块的内部。

您还可以通过allowed_chars

from django.utils.crypto import get_random_string
import string

code = get_random_string(5, allowed_chars=string.ascii_uppercase + string.digits)

答案 2 :(得分:2)

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

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)

答案 3 :(得分:1)

size = 5
''.join(random.choice(string.letters[26:] + string.digits) for in range(size))

这将产生一些短代码,但它们可以重复。所以在保存之前检查它们在数据库中是否是唯一的。

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 constrain,并处理异常。

答案 4 :(得分:1)

从3.6开始,您可以使用secrets模块生成漂亮的随机字符串。 https://docs.python.org/3/library/secrets.html#module-secrets

import secrets
print(secrets.token_hex(5))

答案 5 :(得分:0)

如果您可以在生成的数字中输掉'8'和'9',那么有一种非常Python的解决方案来获取真正的随机数。

import os
import base64

base64.b32encode(os.urandom(3))[:5].decode('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

答案 6 :(得分:0)

django中有一个功能可以满足您的需求(贷记this answer):

  

Django提供的功能get_random_string()可以满足   字母数字字符串生成要求。你什么都不需要   额外的软件包,因为它位于django.utils.crypto模块中。

>>> from django.utils.crypto import get_random_string
>>> unique_id = get_random_string(length=32)
>>> unique_id
u'rRXVe68NO7m3mHoBS488KdHaqQPD6Ofv'
     

您还可以使用allowed_chars来更改字符集:

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

答案 7 :(得分:0)

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

在这种情况下,这就是我生成唯一字符串的方式:


这是我的标准课程Model:

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

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

    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)

但是我所有模型中都有相同的 systemCode 字段。所以我正在使用一个函数来产生价值。

因此,这就是使用 saveSystemCode() 函数为所有模型生成唯一值的方法:

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)

saveSystemCode 函数中的

while 循环阻止再次保存相同的值。

答案 8 :(得分:0)

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

library(RSelenium)
rD <- rsDriver(browser = c("firefox")) #specify browser type you want Selenium to open
remDr <- rD$client

remDr$navigate("https://pro.rarom.ro/istoric_vehicul/dosar_vehicul.aspx") # navigates to webpage

# select first input field
option <- remDr$findElement(using='id', value="inputEmail")
option$highlightElement()
option$clickElement()
option$sendKeysToElement(list("email@email.com"))

# select second input field
option <- remDr$findElement(using='id', value="inputEmail2")
option$highlightElement()
option$clickElement()
option$sendKeysToElement(list("email@email.com"))


# select second input field
option <- remDr$findElement(using='id', value="inputVIN")
option$highlightElement()
option$clickElement()
option$sendKeysToElement(list("123"))

#press key
webElem <- remDr$findElement(using = "id", "trimite")
webElem$highlightElement()
webElem$clickElement()

答案 9 :(得分:0)

如果可以将每个用户与唯一的ID相关联(例如Django或Flask中的> search <- html_form(read_html("http://www.google.com"))[[1]] > filledform<-set_values(search, q = "Tripadvisor") > filledform <form> 'f' (GET /search) <input hidden> 'ie': ISO-8859-1 <input hidden> 'hl': sw-KE <input hidden> 'source': hp <input hidden> 'biw': <input hidden> 'bih': <input text> 'q': Tripadvisor <input submit> 'btnG': Tafuta na Google <input submit> 'btnI': Najisikia Nina Bahati <input hidden> 'iflsig': AINFCbYAAAAAXwh1Gb4SG4gwHsk84hsdtwWV95dbxZLy <input hidden> 'gbv': 1 > submit_form(search,filledform,submit = "btnG") Error in curl::curl_fetch_memory(url, handle = handle) : Protocol "" not supported or disabled in libcurl )。您可以执行以下操作:

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

我们将向右填充Primary Key,以使生成的长度保持不变

user_id

答案 10 :(得分:0)

这是解决文件中长度为 5 或任何长度的代码的解决方案:

import shortuuid as su
n = int(input("# codes to gen: "))
l = int(input("code lenght: "))
shou = su.ShortUUID(alphabet="QWERTYUIOPASDFGHJKLZXCVBNM0123456789")
codes = set()
LEN_CNT = 0

with open('file.txt', 'w') as file:
    while len(codes) < n:
        cd = shou.random(length=l)
        codes.add(cd)
        if len(codes) > LEN_CNT:
            LEN_CNT = len(codes)
            file.write(f"{cd}\n")

(shortuuid 有时会生成重复的代码,所以我使用 set 来处理)