如何使用 UUID

Posted

技术标签:

【中文标题】如何使用 UUID【英文标题】:How to use UUID 【发布时间】:2015-12-08 07:05:50 【问题描述】:

我正在尝试为我的 Django 对象获取唯一 ID。在 Django 1.8 中,它们具有 UUIDField。我不确定如何使用该字段为模型中的每个对象生成唯一 ID。

这是我为 UUIDField 准备的内容

import uuid
from django.db import models

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

class Person(models.Model):
    ...
    unique_id = MyUUIDModel()

我可以重现 UUID 模型的 id,但每次我都得到完全相同的 id。例如:

person = Person.objects.get(some_field = some_thing)
id = person.unique_id.id

id 然后每次都给我相同的 id。怎么了,怎么解决?

【问题讨论】:

【参考方案1】:

我不确定您为什么要创建 UUID 模型。您可以将 uuid 字段直接添加到 Person 模型中。

class Person(models.Model):
    unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)

每个人都应该有一个唯一的 id。如果您希望 uuid 成为主键,您可以这样做:

class Person(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

您当前的代码尚未向此人添加字段。它在您执行 MyUUIDModel() 时创建了一个 MyUUIDModel 实例,并将其保存为类属性。这样做没有意义,每次加载 models.py 时都会创建 MyUUIDModel。如果你真的想使用 MyUUIDModel,你可以使用ForeignKey。然后每个人将链接到不同的 MyUUIDModel 实例。

class Person(models.Model):
    ...
    unique_id = models.ForeignKey(MyUUIDModel, unique=True)

但是,正如我之前所说,最简单的方法是将 UUID 字段直接添加到人员。

【讨论】:

【参考方案2】:

您可以在Person 模型中直接将id 字段添加为UUIDField。不需要单独的MyUUIDModel

我认为您将它与UUIDField example 中使用的MyUUIDModel 混淆了,其中idUUIDField。您可以只使用下面的代码,它将使用UUIDs 代替id

import uuid
from django.db import models

class Person(models.Model):
    ...
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) 

【讨论】:

【参考方案3】:

当你像这样声明你的 Person 模型时,你需要使用你创建的类作为子类:

import uuid
from django.db import models

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

class Person(MyUUIDModel):
  ...

这样 Person 成为 MyUUIDModel 的子类,并将继承其 id 字段定义。

【讨论】:

我认为这似乎捕捉到了 OP 的意图? 您应该将MyUUIDModel 抽象化以避免为其创建表格。如果你不这样做,所有子类MyUUIDModel 的类都将与其 ID 共享一个公用表。见docs.djangoproject.com/en/dev/topics/db/models/…【参考方案4】:

编辑:其实我错了。尚不可能将其实现为DEFAULT_AUTO_FIELD,因为它必须继承自IntegerField。这是the ticket in the django project 的功能请求,以使其成为可能。解决后,我会更新我的答案。


从 Django 3.2 开始,如果您想在项目范围内使用 uuid 作为所有模型的 pk,则不再需要通用抽象模型。只需定义DEFAULT_AUTO_FIELD 设置

默认值

DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

所以这样的东西应该可以工作

DEFAULT_AUTO_FIELD = 'django.db.models.UUIDField'

或者更好的是,创建自己的领域。

DEFAULT_AUTO_FIELD = 'project.common.models.CustomUUIDField'

您还定义了 uuid 类型等。

如文档中所示,它也可以应用于应用级别。

class MyAppConfig(AppConfig):
    default_auto_field = 'project.common.models.CustomUUIDField'

【讨论】:

在 3.2 中,它说 Primary key 'django.db.models.UUIDField' referred by DEFAULT_AUTO_FIELD must subclass AutoField. 是的,这正是我在一个月前添加到此消息的编辑的工单中所写的内容。【参考方案5】:

要在 Django 中将 UUID 用于新模型,请参阅Django Docs。

但是,如果您想将其用于具有与之对应的数据的现有模型unique=True),您将无法直接执行此操作通过上述文档。它将产生迁移错误。 要做到这一点而不会丢失数据,请仔细按照Django Documentation 的所有步骤操作。

【讨论】:

【参考方案6】:

在模型中导入 uuid:

import uuid

在类模型中使用:

class Article(TimeStampedModel):
    uuid = models.UUIDField(editable=False, default=uuid.uuid4, unique=True)
    user = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='articles', null=True)
    categories = models.ManyToManyField(ArticleCategory, blank=True)
    title = models.CharField(max_length=500, null=True, blank=True)
    body = RichTextUploadingField(config_name='portal_lobar_config')
    image = models.ImageField(upload_to='article_images/', null=True, blank=True)
    headline = models.BooleanField(default=True)
    tags = models.ManyToManyField(ArticleTag, blank=True)
    slug = AutoSlugField(max_length=500, populate_from='title', unique_with='created__month', null=True)
    published = models.BooleanField(default=False)
    published_at = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['-created']

【讨论】:

以上是关于如何使用 UUID的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 django 自动创建 uuid 列

如何使用 UUID 作为 HSQLDB 列的默认值

如何使用 UUID

如何在 C++ 中生成 UUID,而不使用 boost 库?

如何在 SQLAlchemy 中使用 UUID?

我们如何强制 ForEach 使用 UUID 而不是 (id: \.self)?