刚刚跳入django 1.8进行快速项目,我发现模型中有UUIDField
。
https://docs.djangoproject.com/en/1.8/ref/models/fields/#uuidfield
我将此用于外部id字段,每个模型都必须公开该对象。 default
参数是否会处理唯一性,还是必须在保存中写入?我的意思是我知道几乎没有值碰撞的机会,只是知道它是如何在内部完成的
答案 0 :(得分:6)
每次UUID模块如何保证唯一值?
RFC 4122(UUID模块规范)指定了三种生成UUID的算法:
在所有情况下,种子值与系统时钟和时钟序列值组合在一起(以便在时钟向后设置时保持唯一性)。因此,根据上述机制生成的UUID将是已经或将要分配的所有其他UUID的唯一。
取自RFC 4122 Abstract:
UUID长128位,可以保证跨空间的唯一性 时间。
注意:由于UUIDS的这种唯一性属性,Django没有在内部检查(如@FlipperPA所述)来检查是否已存在具有相同{{1}的另一个对象}。
答案 1 :(得分:2)
Django不强制执行UUID的唯一性。这是因为UUID的主要用例是提供一个标识符,该标识符可以是唯一的,而不必检查集中的权限(如数据库,这是unique=True
所做的)
(请注意,UUID不保证是唯一的,只有an astronomically small chance of a collision。)
如果你愿意,你当然可以使用数据库在UUID之上强制实现唯一性(通过在你的字段上设置unique=True
),但我会说这是一个不寻常的,很难证明的配置。
答案 2 :(得分:1)
不,它没有。以下是Django代码的相关部分:
def get_db_prep_value(self, value, connection, prepared=False):
if isinstance(value, six.string_types):
value = uuid.UUID(value.replace('-', ''))
if isinstance(value, uuid.UUID):
if connection.features.has_native_uuid_field:
return value
return value.hex
return value
正如您所看到的,在为数据库准备值时,简单地调用uuid并使用连字符替换;没有检查现有的独特性。也就是说,UUIDField继承自Field类,它将遵循Django模型的独特定义。
答案 3 :(得分:0)
我喜欢使用UUID作为主键,我喜欢不为最终用户提供500个错误,只需创建登录等简单操作即可。所以我的模型中有以下类方法。我在生产数据库中抽取一些预先指定的合成交易保留guid,并且不希望那些碰撞。宇宙闪电之前已经发生过变化,下面代码的一个变体(用于报告碰撞)实际上已经开始了第二次guid分配尝试。下面显示的代码仍然存在来自不同应用服务器的并发写入冲突的风险,因此如果视图中的写入/创建操作失败,我的视图将返回到此方法。
我确实认为这个代码比db查找的时间成本慢,但是当guid是我的pk时,当底层数据库在字段上使用b-tree索引时,它并不是非常昂贵。
@classmethod
def attempt_to_set_guid(cls,attemptedGuid=None):
while(True):
try:
if attemptedGuid is None:
attemptedGuid = uuid4()
elif (attemptedGuid in cls.reserved_guids):
attemptedGuid = uuid4()
continue
alreadyExists = Guid.objects.get(guid=attemptedGuid)
break
except Exception as e:
break
return attemptedGuid