由于一些原因^,我想在我的一些Django模型中使用UUID作为主键。如果我这样做了,我还能使用诸如"contrib.comments“、"django-voting”或"django-tagging“这样的外部应用吗?这些应用通过ContentType使用泛型关系?
以"django-voting“为例,投票模型如下所示:
class Vote(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
object = generic.GenericForeignKey('content_type', 'object_id')
vote = models.SmallIntegerField(choices=SCORES)这个应用程序似乎假设被投票的模型的主键是一个整数。
不过,内置的评论应用程序似乎能够处理非整数PKs:
class BaseCommentAbstractModel(models.Model):
content_type = models.ForeignKey(ContentType,
verbose_name=_('content type'),
related_name="content_type_set_for_%(class)s")
object_pk = models.TextField(_('object ID'))
content_object = generic.GenericForeignKey(ct_field="content_type", fk_field="object_pk")这种“整数PK假设”的问题是不是第三方应用程序的常见情况,这会使使用UUID成为一种痛苦?或者,可能,我误解了这种情况?
有没有一种方法可以在Django中使用UUID作为主键而不会造成太多麻烦?
^一些原因:隐藏对象计数,防止url "id爬行“,使用多个服务器创建不冲突的对象,...
发布于 2010-10-16 00:35:24
UUID主键不仅会导致泛型关系的问题,而且还会导致效率方面的问题:每个外键的存储和连接成本都要比机器字高得多。
但是,不需要UUID作为主键:只需通过使用unique=True补充模型的uuid字段,使其成为辅键即可。像平常一样使用隐式主键(在系统内部),并使用UUID作为外部标识符。
发布于 2015-02-12 12:54:46
As seen in the documentation,从Django1.8开始有一个内置的UUID字段。使用UUID与使用整数时的性能差异可以忽略不计。
import uuid
from django.db import models
class MyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)你也可以通过check this answer获取更多信息。
发布于 2019-11-07 04:21:45
将UUID用作PK的真正问题是与非数字标识符相关的磁盘碎片和插入性能下降。因为PK是一个聚集索引(除了PostgreSQL之外的几乎所有RDBMS中),当它不是自动递增的时候,在插入具有较低序号的行时,您的DB引擎将不得不重新使用您的物理驱动器,这将一直发生在UUID中。当您在数据库中获得大量数据时,仅插入一条新记录就可能需要几秒钟甚至几分钟。并且您的磁盘最终会变得碎片,需要定期进行磁盘碎片整理。这一切真的很糟糕。
为了解决这些问题,我最近提出了以下我认为值得分享的架构。
UUID伪主键
此方法允许您利用UUID作为主键的优势(使用唯一索引UUID),同时维护自动递增的PK,以解决拥有非数字PK带来的碎片和插入性能下降问题。
工作原理:
pkid的自动递增主键。id字段,以允许您按UUID id而不是数字主键进行搜索。to_field='id'),以允许外键正确表示伪PK而不是数字ID。<代码>H213<代码>G214基本上,您将执行以下操作:
首先,创建一个抽象的Django基础模型
class UUIDModel(models.Model):
pkid = models.BigAutoField(primary_key=True, editable=False)
id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
class Meta:
abstract = True确保扩展基本模型,而不是models.Model
class Site(UUIDModel):
name = models.CharField(max_length=255)还要确保您的ForeignKeys指向UUID id字段,而不是自动递增的pkid字段:
class Page(UUIDModel):
site = models.ForeignKey(Site, to_field='id', on_delete=models.CASCADE)如果您正在使用Django Rest Framework (DRF),请确保还创建了一个基本ViewSet类来设置默认搜索字段:
class UUIDModelViewSet(viewsets.ModelViewSet):
lookup_field = 'id' 并扩展它而不是你的API视图的基础ModelViewSet:
class SiteViewSet(UUIDModelViewSet):
model = Site
class PageViewSet(UUIDModelViewSet):
model = Page有关本文中的原因和方法的更多说明:https://www.stevenmoseley.com/blog/uuid-primary-keys-django-rest-framework-2-steps
https://stackoverflow.com/questions/3936182
复制相似问题