模型字段唯一性验证错误处理
Model Field uniqueness validation error handling
我有一个名为 ( 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 的正确方法是什么?
所以您的模型声明的问题是您默认使用了 generate_id()
,因此该调用的输出被用作默认值。
试试这个
unique_id = models.CharField(db_index=True, default=generate_id)
每次创建对象时都会调用生成 id
参考:https://docs.djangoproject.com/en/1.9/ref/models/fields/#default
首先,正如@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
装饰器。这只有在实例化 Field
对象之前定义了 _generate_id
才有可能,并且它只适用于 @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)
但我本人从未在现实生活中尝试过。
我有一个名为 ( 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 的正确方法是什么?
所以您的模型声明的问题是您默认使用了 generate_id()
,因此该调用的输出被用作默认值。
试试这个
unique_id = models.CharField(db_index=True, default=generate_id)
每次创建对象时都会调用生成 id
参考:https://docs.djangoproject.com/en/1.9/ref/models/fields/#default
首先,正如@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
装饰器。这只有在实例化 Field
对象之前定义了 _generate_id
才有可能,并且它只适用于 @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)
但我本人从未在现实生活中尝试过。