You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 19:20:33