生成随机字母数字字符串作为模型的主键 [英] Generate a random alphanumeric string as a primary key for a model

查看:139
本文介绍了生成随机字母数字字符串作为模型的主键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



例如:

 从django.db导入模型

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


$ b $在我看来,关键应该是这样的Ay3kJaBdGfcadZdao03293。这是非常临时使用的。如果发生碰撞,我希望Django尝试一个新的密钥。



我想知道是否已经有了某些东西,或者我看不到的一个非常简单的解决方案(我对python和Django来说比较新)。否则我正在考虑做自己的版本的 models.AutoField ,那会是正确的方法吗?



我已经发现如何生成密钥这里,所以它不是关于字符串生成。我只想使它与一个简单的Django服务无缝工作,而不会增加代码的复杂性。



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

  id = models.CharField(unique = True,primary_key = True,default = StringKeyGenerator() = False)

 $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 
b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b返回''.join(random.choice(string.letters + string.digits)for x in range(self.lenght))

我再次经历了Django文档后想到了。

解决方案

不要使该字段成为主键:

 从django.db import IntegrityError 

class MyTemporaryObject(models.Model):
auto_pseudoid = models.CharField(max_length = 16,blank = True,editable = False,unique = True)
#add index =它
#blank = True是可以验证的存储之前的对象 - 保存方法将确保它获取一个值

#其他字段如所需

def save(self,* args,** kwargs):
如果不是self.auto_pseudoid:
self.auto_pseudoid = generate_random_alphanumeric(16)
#使用你的函数如上或任何其他
success = False
failures = 0
但不成功:
try:
super(MyTemporaryObject,self).save(* args,** kwargs)
除了IntegrityError:
failures + = 1
如果失败> 5:#或某些其他任意截断点,事情明显错误
raise
else:
#看起来像一个碰撞,尝试另一个随机值
self.auto_pseudoid = generate_random_alphanumeric( 16)
else:
success = True

这个避免的两个问题,相比之下,使用该字段作为主要的关键是:



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



2)Django使用数据库中主键的存在作为一个标志, save 应更新现有记录,而不是插入新记录。这意味着如果您在主键字段中遇到冲突,则会默认覆盖该行中的其他任何值。


I would like a model to generate automatically a random alphanumeric string as its primary key when I create a new instance of it.

example:

from django.db import models

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

in my mind the key should look something like this "Ay3kJaBdGfcadZdao03293". It's for very temporary use. In case of collision I would like it Django to try a new key.

I was wondering if there was already something out there, or a very simple solution I am not seeing (I am fairly new to python and Django). Otherwise I was thinking to do my own version of models.AutoField, would that be the right approach?

I have already found how to generate the key here, so it's not about the string generation. I would just like to have it work seamlessly with a simple Django service without adding too much complexity to the code.

EDIT: Possible solution? What do you think?

id = models.CharField(unique=True, primary_key=True, default=StringKeyGenerator(), editable=False)

with

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))

I came up with it after going through the Django documentation one more time.

解决方案

Here's how I would do it without making the field a primary key:

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

Two problems that this avoids, compared to using the field as the primary key are that:

1) Django's built in relationship fields require integer keys

2) Django uses the presence of the primary key in the database as a sign that save should update an existing record rather than insert a new one. This means if you do get a collision in your primary key field, it'll silently overwrite whatever else used to be in the row.

这篇关于生成随机字母数字字符串作为模型的主键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆