首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >生成一个随机字母数字字符串作为模型的主键

生成一个随机字母数字字符串作为模型的主键
EN

Stack Overflow用户
提问于 2013-12-05 13:53:12
回答 3查看 10.4K关注 0票数 9

当我创建一个新的实例时,我希望一个模型自动生成一个随机的字母数字字符串作为它的主键。

示例:

代码语言:javascript
复制
from django.db import models

class MyTemporaryObject(models.Model):
    id = AutoGenStringField(lenght=16, primary_key=True)
    some_filed = ...
    some_other_field = ...

在我看来,密钥应该类似于"Ay3kJaBdGfcadZdao03293“。这是非常临时的使用。在冲突的情况下,我希望Django尝试一个新的密钥。

我想知道是不是已经有了一些东西,或者是一个我没有看到的非常简单的解决方案(我对python和Django相当陌生)。否则我想做我自己版本的models.AutoField,这是正确的方法吗?

我已经找到了如何生成密钥here,所以这与字符串生成无关。我只是想让它与一个简单的Django服务无缝工作,而不会给代码增加太多的复杂性。

编辑:可能的解决方案?你认为如何?

代码语言:javascript
复制
id = models.CharField(unique=True, primary_key=True, default=StringKeyGenerator(), editable=False)

使用

代码语言:javascript
复制
class StringKeyGenerator(object):
    def __init__(self, len=16):
        self.lenght = len
    def __call__(self):
        return ''.join(random.choice(string.letters + string.digits) for x in range(self.lenght))

我是在再看一遍Django文档后想出来的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-12-05 14:44:41

下面是我如何在不将字段设置为主键的情况下完成此操作:

代码语言:javascript
复制
from django.db import IntegrityError

class MyTemporaryObject(models.Model):
    auto_pseudoid = models.CharField(max_length=16, blank=True, editable=False, unique=True)
    # add index=True if you plan to look objects up by it
    # blank=True is so you can validate objects before saving - the save method will ensure that it gets a value

    # other fields as desired

    def save(self, *args, **kwargs):
        if not self.auto_pseudoid:
            self.auto_pseudoid = generate_random_alphanumeric(16)
            # using your function as above or anything else
        success = False
        failures = 0
        while not success:
            try:
                super(MyTemporaryObject, self).save(*args, **kwargs)
            except IntegrityError:
                 failures += 1
                 if failures > 5: # or some other arbitrary cutoff point at which things are clearly wrong
                     raise
                 else:
                     # looks like a collision, try another random value
                     self.auto_pseudoid = generate_random_alphanumeric(16)
            else:
                 success = True

与使用字段作为主键相比,这样可以避免两个问题:

1) Django的内置关系字段需要整数键

2) Django使用数据库中主键的存在作为save应该更新现有记录而不是插入新记录的标志。这意味着如果您的主键字段中确实存在冲突,它将悄悄地覆盖行中以前的任何其他内容。

票数 5
EN

Stack Overflow用户

发布于 2013-12-05 14:05:44

在python中生成唯一字符串的最简单方法之一是使用uuid模块。如果你想得到字母数字输出,你也可以简单地使用base64编码:

代码语言:javascript
复制
import uuid
import base64
uuid = base64.b64encode(uuid.uuid4().bytes).replace('=', '')
# sample value: 1Ctu77qhTaSSh5soJBJifg

然后,您可以将此代码放入模型的save方法中,或者使用它定义一个自定义模型字段。

票数 15
EN

Stack Overflow用户

发布于 2015-06-15 05:10:43

试试这个:

下面的if语句是为了确保模型是可更新的。

如果没有if语句,您将在每次重新保存模型时更新id字段,因此每次都会创建一个新模型

代码语言:javascript
复制
from uuid import uuid4
from django.db import IntegrityError

class Book(models.Model):
    id = models.CharField(primary_key=True, max_length=32)

    def save(self, *args, **kwargs):
        if self.id:
            super(Book, self).save(*args, **kwargs)
            return

        unique = False
        while not unique:
            try:
                self.id = uuid4().hex
                super(Book, self).save(*args, **kwargs)
            except IntegrityError:
                self.id = uuid4().hex
            else:
                unique = True
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20392497

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档