如何基于关联模型字段生成Django模型的custom_id字段
Django模型生成自定义custom_id报错解决
问题背景
需要为CompanyUserPhysicalCard模型生成格式如「123456GOOGLE」的custom_id,由随机字符拼接公司名称组成。使用自定义默认函数company_card_code时触发错误:'ForeignKey' object has no attribute 'company_name'。
相关代码
models.py
class CompanyUserPhysicalCard(models.Model): card = models.ForeignKey(Cards, on_delete=models.CASCADE, related_name='company_physical_user_cards') company = models.ForeignKey(Company, on_delete=models.SET_NULL, null=True, verbose_name='компания') custom_id = models.CharField(max_length=7, unique=True, default=company_card_code, editable=False, null=True, blank=True)
自定义函数
def company_card_code(company): letters = '01234567890QLUBOK' result_str = ''.join(random.choice(letters) for i in range(9)) + str(company.company_name) return result_str
报错信息
'ForeignKey' object has no attribute 'company_name'
解决方案
错误原因
Django字段的default参数在模型类加载阶段就会执行,此时传入函数的是ForeignKey字段对象,而非实际创建的Company实例,自然无法访问company_name属性。
修正方案:重写模型save方法
放弃default参数,通过重写save方法在实例保存时生成custom_id,此时已能获取关联的Company实例:
import random class CompanyUserPhysicalCard(models.Model): card = models.ForeignKey(Cards, on_delete=models.CASCADE, related_name='company_physical_user_cards') company = models.ForeignKey(Company, on_delete=models.SET_NULL, null=True, verbose_name='компания') # 调整max_length以容纳随机字符+公司名称,示例设为20可根据实际需求修改 custom_id = models.CharField(max_length=20, unique=True, editable=False, null=True, blank=True) def save(self, *args, **kwargs): # 仅当custom_id为空且关联了company时生成 if not self.custom_id and self.company: letters = '0123456789QLUBOK' # 移除重复的0,避免字符分布不均 # 生成6位随机字符(匹配示例中的123456格式) random_segment = ''.join(random.choice(letters) for _ in range(6)) # 拼接大写的公司名称 self.custom_id = f"{random_segment}{self.company.company_name.upper()}" # 处理唯一约束:若生成的custom_id已存在,重新生成 while CompanyUserPhysicalCard.objects.filter(custom_id=self.custom_id).exists(): random_segment = ''.join(random.choice(letters) for _ in range(6)) self.custom_id = f"{random_segment}{self.company.company_name.upper()}" # 调用父类save方法完成保存 super().save(*args, **kwargs)
关键说明
- 长度调整:原
max_length=7无法容纳随机字符+公司名称,需根据实际公司名称长度调整为合适值。 - 去重处理:随机字符串存在重复概率,通过循环检查确保
custom_id唯一性。 - 判空逻辑:仅在
custom_id为空时生成,避免更新实例时覆盖已有值。 - 格式统一:将公司名称转为大写,匹配示例中的格式要求。
内容的提问来源于stack exchange,提问作者Zesshi
相关产品推荐
相关产品推荐

