使用Model.objects.create()

时间:2019-03-27 13:53:07

标签: django postgresql

我的模型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中指出的那样,自定义模型方法在迁移中不可用。我将不得不将模型的保存方法复制到迁移文件中。

2 个答案:

答案 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字段旁边添加另一个字段。