在Django中从模型字段生成唯一ID

59

我希望在Django中从模型字段生成每个请求的不同/唯一ID。我尝试了这个方法,但是我一直得到相同的ID。

class Paid(models.Model):
     user=models.ForeignKey(User)
     eyw_transactionref=models.CharField(max_length=100, null=True, blank=True, unique=True, default=uuid.uuid4()) #want to generate new unique id from this field

     def __unicode__(self):
        return self.user
5个回答

139

自1.8版本以来,Django拥有UUIDField

import uuid
from django.db import models

class MyUUIDModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    # other fields

25
如果你使用的是 Django 1.8 及以上版本,那么这就是实际的答案。 - Paulo Bu
2
@Sevenearths https://dev59.com/VI3da4cB1Zd3GeqPwCoe@Sevenearths https://dev59.com/VI3da4cB1Zd3GeqPwCoe%E7%9A%84new-uuidfields%E7%9A%84default%E5%B1%9E%E6%80%A7%E8%83%BD%E5%A4%9F%E5%A4%84%E7%90%86%E5%94%AF%E4%B8%80%E6%80%A7%EF%BC%9F - madzohan
1
我使用了你的解决方案,但是值一直在变化。为什么会这样? - Max Will

64
如果您正在使用Django 1.8或更高版本,madzohan的答案是正确的答案。
像这样做:
#note the uuid without parenthesis
eyw_transactionref=models.CharField(max_length=100, blank=True, unique=True, default=uuid.uuid4)
因为使用括号,你会在模型导入时评估函数,这将产生一个uuid,该uuid将用于创建的每个实例。
如果没有括号,只传递需要调用的函数以为字段提供默认值,它将在每次导入模型时被调用。
你也可以采取这种方法:
class Paid(models.Model):
     user=models.ForeignKey(User)
     eyw_transactionref=models.CharField(max_length=100, null=True, blank=True, unique=True)

     def __init__(self):
         super(Paid, self).__init__()
         self.eyw_transactionref = str(uuid.uuid4())

     def __unicode__(self):
        return self.user

1
我已经这样做了...现在我的数据库中得到了NULL,这意味着它没有保存!我应该发布我的观点吗? - picomon
2
如果您有默认值,则在字段定义中不需要使用null=True。我会从答案中删除它。请尝试不使用它。 - Paulo Bu
1
现在出现了这个错误IntegrityError at /pay/ (1048,“列'eyw_transactionref'不能为空”)。我也删除了blank=True。 - picomon
1
有点奇怪。它应该可以工作,我会在__init__方法中加入一个覆盖选项。 - Paulo Bu
1
也可以尝试使用默认值,也许会起作用:default=lambda:str(uuid.uuid4()) - Paulo Bu
显示剩余8条评论

29

如果您需要或想要使用自定义的ID生成函数而不是Django的UUID字段,您可以在save()方法中使用while循环。对于足够大的唯一ID,这几乎永远不会导致多次数据库调用以验证唯一性:

urlhash = models.CharField(max_length=6, null=True, blank=True, unique=True)

# Sample of an ID generator - could be any string/number generator
# For a 6-char field, this one yields 2.1 billion unique IDs
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

def save(self):
    if not self.urlhash:
        # Generate ID once, then check the db. If exists, keep trying.
        self.urlhash = id_generator()
        while MyModel.objects.filter(urlhash=self.urlhash).exists():
            self.urlhash = id_generator()
    super(MyModel, self).save()

2

1
你可以使用 UUID 完成这个任务。 UUID 字段是用来存储通用唯一标识符的特殊字段。 通用唯一标识符是主键 AutoField 的一个不错的替代方案。数据库不会为你生成 UUID,建议使用默认值。
import uuid
from django.db import models
class MyUUIDModel(models.Model):
   id = models.UUIDField(
     primary_key = True,
     default = uuid.uuid4,
     editable = False)

要了解更多详细信息,请访问此链接


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接