【问题标题】:Random string not random [duplicate]随机字符串不是随机的[重复]
【发布时间】:2020-05-13 19:27:30
【问题描述】:

我正在尝试在我的数据库中为用户创建一个随机字符串。这是无密码登录的一部分。

所以我有一个应该生成随机字符串的字段。但我刚刚发现它没有。它实际上一遍又一遍地生成相同的字符串。也许每 5-10 分钟它会在几分钟内生成一个新字符串。

我的模型看起来像这样。

class Random(models.Model):  
    user = models.OneToOneField('CustomUser', on_delete=models.CASCADE)
    random = models.CharField(max_length=25, default=uuid.uuid4().hex[:25].upper(), unique=True)
    created_at = models.DateTimeField(auto_now_add=True)

即使它生成一个 25 长的字符串,它也会一遍又一遍地复制它。

由于我有唯一的 true,这导致下一次调用创建字符串是不可能的,因为它不是唯一的。

为什么每次都是独一无二的?

【问题讨论】:

  • default=uuid.uuid4() 这里 uuid.uuid4() 在服务器首次执行并定义模型时评估一次。
  • @sumpen 有什么理由跳过 uuid4 的一部分吗?
  • @funnydman 我不明白你的意思?
  • @sumpen 为什么需要uuid.uuid4().hex[:25]?它看起来很奇怪,我不建议这样做。
  • @funnydman 我会用什么代替?

标签: django python-3.x django-models


【解决方案1】:

您的默认值将在运行前计算,而不是在运行期间计算。您需要定义一个可调用对象,根据Django documentation,它将在“每次创建新对象时”被调用。

例子:

def calculate_random():
    return uuid.uuid4().hex[:25].upper()

class Random(models.Model):
    random = models.CharField(max_length=25, default=calculate_random, unique=True)

【讨论】:

    【解决方案2】:

    最好使用UUIDField,它被设计用来存储uuid,并将被转换为相应的DB类型,uuid如果数据库支持,否则将使用CharField作为后备。

    例如:

    import uuid
    
    class Random(models.Model):  
        random = models.UUIDField(default=uuid.uuid4, unique=True)
    

    简单明了。

    【讨论】:

    • 我不明白为什么这比其他答案更好?我也可以用这个解决方案选择字符串的长度吗?
    • @sumpen uuid4 格式是严格定义的,有 36 个字符,不能有更多或更少,如果这个规则被打破(这里更多)它不再是 uuid。如果您需要真正的唯一性,请不要截断它。
    • @sumpen 这个是 real 正确答案,因为它正确使用了uuid - 截断 uuid 的字符串表示形式会破坏在全部(如果你想要随机的唯一标识符,你将很难得到比正确的 uuid 更好的东西)。
    • @funnydman 所以这样,它会为数据库的每个新条目生成一个新的唯一 uuid?
    • @sumpen 是的,将为每条新记录生成唯一的 UUID。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    • 2015-11-06
    • 2010-12-07
    • 2011-12-08
    • 2013-04-29
    相关资源
    最近更新 更多