在Django中为模型创建一个21个字符的唯一字段

时间:2016-12-21 18:10:48

标签: python django django-models

我知道id本身是独一无二的,我想创建一个更长,更不易猜测的独特字段。简而言之,该字段将是一个唯一的21个字符的字母数字字符串。我这样做是使用以下代码:

class Organization(models.Model):
    name = models.CharField(max_length=255)
    key = models.CharField(max_length=21, unique=True, blank=True, null=True)

    def save(self, *args, **kwargs):
        if self.key == '' or self.key == None:
            key = ''
            for i in range(21):
                key += random.choice(string.lowercase + string.uppercase + string.digits)

            if Organization.objects.filter(key=key).exists():
                self.save() # Try again
            else:
                self.key = key
        super(Organization, self).save(*args, **kwargs)

save方法中,我执行以下操作:

  • 查看对象的密钥是否存在。
  • 如果没有,我会生成一个21个字符的密钥。
  • 然后我检查是否存在具有我生成的密钥的组织。
  • 如果没有,则将对象的密钥设置为生成的密钥并保存。

这是正确的方法吗?

是否有更好的方法可能会少用代码?另外,请注意我的关键字段是如何唯一的,但也可以是空白的。这可能是个问题吗?到目前为止,这已经很好了。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:2)

现在,您似乎正在尝试使用CharField模拟UUID(通用唯一标识符)。虽然这种方法可能不会引起太多问题(它确实提供了(26 + 26 + 10)** 21种可能的组合),但这是一种非常天真的方法。

为什么不使用Django的原生UUIDField?这是一个例子:

class Organization(models.Model):
    name = models.CharField(max_length=255)
    key = models.UUIDField(default=uuid.uuid4, editable=False)

这将使用uuid Python模块。它将生成一个随机的UUID:

In [1]: uuid.uuid4()
Out[1]: UUID('3be0e5db-eb0a-4f09-bda3-37006760ab38')

In [2]: uuid.uuid4()
Out[2]: UUID('8d916804-0a53-478e-8e4f-ebda5d7a69ab')

显然,这些UUID是十六进制的并且包含连字符,但我认为最好遵循这个约定而不是定义自己的唯一标识符。

答案 1 :(得分:0)

你可以uuid4。但我个人更喜欢CharField并将uuid4字符指定为默认值。原因是UUIDField在查询DB时会带来很多不便。

  • 如果要在以pythonic方式生成UUID代码后添加一行(通过插入原始数据库命令),如果您尝试迭代DJANGO-QUERIED对象,则会出现一些问题。

通过将uuid代码分配给默认值,如下所示,

from django.db import models
import uuid

class Person(models.Model):

    name = models.CharField(max_length=255)
    code = models.CharField(max_length=8, unique=True, default=uuid.uuid4)