Django模型自定义主键ID自动生成非重复值的问题与解决
问题描述
在Django模型中设置了一个CharField类型的主键ID字段,定义如下:
my_id = models.CharField(primary_key=True, max_length=5, validators=[RegexValidator( regex=ID_REGEX, message=ID_ERR_MSG, code=ID_ERR_CODE )])
需求是为该字段添加默认值逻辑:调用全局或类函数遍历现有ID,找到第一个未被使用的ID分配给新用户。但设置blank=foo()时,出现“函数不存在”的错误。
尝试过程
Edit1
尝试将生成ID的函数放到单独的utils文件中导入使用,但由于函数需要调用模型类查询对象,出现循环导入错误。
Edit2
调整后解决了循环导入问题,但出现新错误:
TypeError: super(type, obj): obj must be an instance or subtype of type
此前正常工作的save重写函数如下:
def save(self, *args, **kwargs): self.full_clean() super(Staff, self).save(*args, **kwargs)
自定义生成ID的函数代码:
def get_id_default(): from .models import MyObj for temp_id in range(10_000, 100_000): try: MyObj.objects.get(my_id=str(temp_id)) except ObjectDoesNotExist: break # 该ID不存在 return str(hive_id)
Edit3
尝试通过kwargs获取my_id,但kwargs为空,无法实现逻辑:
def save(self, *args, **kwargs): print(kwargs) # 输出 {} if kwargs["my_id"] is None: kwargs["my_id"] = self.get_id_default() self.full_clean() super(Staff, self).save(*args, **kwargs)
其中get_id_default为类方法:
def get_id_default(self): for temp_id in range(10_000, 100000): try: self.objects.get(my_id=str(temp_id)) except ObjectDoesNotExist: break # 该ID不存在 return str(temp_id)
最终解决方案
Solution1:使用utils文件中的自定义默认函数
创建utils文件,编写生成默认值的函数,在模型中导入并设置为字段的default参数:
utils文件代码:
from .models import MyModel def my_custom_default(): # 自定义逻辑:找到第一个未使用的ID return 生成的ID值
模型文件(main.models.py)中:
from django.db import models from .my_utils import my_custom_default class MyModel(models.Model): my_field = models.CharField(primary_key=True, max_length=5, validators=[RegexValidator( regex=ID_REGEX, message=ID_ERR_MSG, code=ID_ERR_CODE )], default=my_custom_default)
Solution2:模型类中定义静态函数+重写save方法
在模型类中创建静态函数生成默认ID,字段设置default=None,并重写save方法:
静态函数定义:
@staticmethod def get_my_default(): # 自定义逻辑:遍历找到第一个未使用的ID for temp_id in range(10_000, 100000): try: MyModel.objects.get(my_id=str(temp_id)) except ObjectDoesNotExist: break return str(temp_id) # 注意:最初尝试用self调用objects(self.objects.get(...)),会触发异常:AttributeError: Manager isn't accessible via Sites instances
重写save方法:
def save(self, *args, **kwargs): if self.my_id is None: self.my_id = self.get_my_default() self.full_clean() super().save(*args, **kwargs)
内容的提问来源于stack exchange,提问作者pb.
相关产品推荐
相关产品推荐

