我的模型Image
中有一个主键ID CharField,我想为新创建的对象创建唯一的ID。我试图通过重写模型的save方法来实现这一点:
def save(self, *args, **kwargs):
if not self.pk: # is created
self.id = uuid.uuid4().hex
while Image.objects.filter(id=self.id).exists():
self.id = uuid.uuid4().hex
return super().save(*args,**kwargs)
问题是,当我使用save()
创建对象时似乎没有调用Image.objects.create()
,仅当我使用image=Image(...)
创建对象然后调用{{ 1}}。结果,除非指定了新创建的对象,否则未分配ID,这会导致PostgreSQL引发image.save()
错误。
如何确保在调用non_unique primary key
时创建了唯一ID?
Django版本:1.11.3
更新:我意识到被覆盖的save()方法也没有被调用。原来问题是我在迁移中调用模型的Image.objects.create()
方法。正如this post中指出的那样,自定义模型方法在迁移中不可用。我将不得不将模型的保存方法复制到迁移文件中。
答案 0 :(得分:2)
通常无法完成此操作。在检查该ID尚不存在的if语句与您对其进行设置之间,其他操作可能会添加一个具有该ID的新行。这就是为什么要使用其他解决方案的原因-数据库确保的自动递增ID是唯一的,或者UUID很少有唯一的机会。
幸运的是,您使用其中之一。对于UUID,习惯是假设它们是唯一的。
方法是将返回唯一ID的函数设置为该字段的默认值:
def uuid_hex():
return uuid.uuid4().hex
class YourModel(models.Model):
id = CharField(unique=True, primary_key=True, default=uuid_hex, null=False)
答案 1 :(得分:0)
您应在覆盖模型save
方法的同时调用真实的save
方法:
def save(self, *args, **kwargs):
if not self.pk: # is created
self.id = uuid.uuid4().hex
while Image.objects.filter(id=self.id).exists():
self.id = uuid.uuid4().hex
super(Image, self).save(*args, **kwargs)
检查文档: Overriding predefined model methods
此外,覆盖默认的id
也不是一个好主意。如果您需要另一个唯一字段用作ID之类的东西,那么我建议在默认id
字段旁边添加另一个字段。