模型字段唯一性验证错误处理

时间:2016-06-21 07:52:29

标签: django validation model uniqueidentifier

我有一个名为(unique_id)的模型字段,它生成一个随机字符串。它在模型调用Posts中定义。

unique_id = models.CharField(db_index=True, default=generate_id())

generate_id函数是

import random
a = 'ABCDEFJHIJKLMNOPQRSTUVWXYZabcdefjhijklmnopqrstuvwxyz_-123456789'       

def generate_id(length=6):
        return ''.join(random.choice(a) for i in range(length))
如果django不是唯一的,那么它将会引发IntegrityError: UNIQUE constraint failed

在数据库级别避免重复唯一IDS的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

首先,当@DanielRoseman说不调用default中的函数时,可以将default值设置为callable,这样更好,因为它会在每次创建对象时调用函数,但是如果你调用它在字段定义中,它将在内部时间调用一次

unique_id = models.CharField(db_index=True, default=generate_id)

其次我建议使用UUIDField,这会为你生成随机字符串。

为了解决您的问题,您有两种方法。生成相当长的unique_id,至少12个字符长,这几乎可以保证您不会发生任何碰撞。或者您可以在generate_id功能

中添加数据库检查
def generate_id(length=6):
    unique_id = ''.join(random.choice(a) for i in range(length))
    while Mymodel.objects.filter(unique_id=unique_id).exists():
        unique_id = ''.join(random.choice(a) for i in range(length))
    return unique_id

回答评论 方法中的模型可以通过self.__class__访问,如下面的示例

class Post(models.Model):
    def _generate_id(self, length=6):
        unique_id = ''.join(random.choice(a) for i in range(length))
        while self.__class__.objects.filter(unique_id=unique_id).exists():
            unique_id = ''.join(random.choice(a) for i in range(length))
        return unique_id

但如果它是方法,您将无法将其作为默认值添加到字段,因为不会有self实例。但您可以尝试使用@classmethod装饰器。只有在实例化_generate_id对象之前定义Field并且它只能与@classmethods一起使用才有可能,因为在python类中它们是自己的小名称空间。

class Post(models.Model):
    @classmethod
    def _generate_id(cls, length=6):
        unique_id = ''.join(random.choice(a) for i in range(length))
        while cls.objects.filter(unique_id=unique_id).exists():
            unique_id = ''.join(random.choice(a) for i in range(length))
        return unique_id

    unique_id = models.CharField(db_index=True, default=_generate_id, max_length=12)

但我自己从未在现实生活中尝试过这一点。

答案 1 :(得分:0)

因此,模型声明的问题是您使用了默认的generate_id(),因此该调用的输出被用作默认值。

尝试使用此

unique_id = models.CharField(db_index=True, default=generate_id)

每次创建对象时都会调用generate id

参考:https://docs.djangoproject.com/en/1.9/ref/models/fields/#default