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

le-*_*ude 9 python django postgresql

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

例:

from django.db import models

class MyTemporaryObject(models.Model):
    id = AutoGenStringField(lenght=16, primary_key=True)
    some_filed = ...
    some_other_field = ...
Run Code Online (Sandbox Code Playgroud)

在我看来,键应该看起来像这样的"Ay3kJaBdGfcadZdao03293".这是非常临时使用的.如果发生碰撞,我希望Django尝试新密钥.

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

我已经找到了如何在这里生成密钥,因此它不是关于字符串生成的.我只想让它与简单的Django服务无缝协作,而不会给代码增加太多的复杂性.

编辑:可能的解决方案?你怎么看?

id = models.CharField(unique=True, primary_key=True, default=StringKeyGenerator(), editable=False)
Run Code Online (Sandbox Code Playgroud)

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))
Run Code Online (Sandbox Code Playgroud)

在再次浏览Django文档之后我想出了它.

Ami*_*ari 15

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

import uuid
import base64
uuid = base64.b64encode(uuid.uuid4().bytes).replace('=', '')
# sample value: 1Ctu77qhTaSSh5soJBJifg
Run Code Online (Sandbox Code Playgroud)

然后,您可以将此代码放在模型的save方法中,或使用它定义自定义模型字段.

  • 这不是字母数字:`R0oX1ebxQpepGQ/JQsGpNw`,`uCRmokb7QFC + zQCs1hBqNA`. (2认同)

Pet*_*per 5

以下是我将如何在不将该字段设为主键的情况下执行此操作:

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
Run Code Online (Sandbox Code Playgroud)

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

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

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