在Django中如何提取产品序列号字符串末尾数字并转换为Int实现自增
Django 产品序列号生成逻辑修正方案
原有代码核心问题
- 年份判断逻辑错误:年份为4位数字,原有代码截取序列号前3位
[0:3]进行判断,永远无法和当前4位年份匹配 - 变量号提取&自增逻辑错误:序列号末尾的变量号为3位,原有代码仅截取最后1位
[-1],且自增运算符写反为=+1,实际效果是直接赋值为1,无法实现自增 - 初始变量号不符合规则:需求中初始变量号为101,原有代码赋值为10,输出结果不符合序列号规则
- 代码冗余:三个分支中年份前缀、产品名称缩写的赋值逻辑完全重复,可统一提取
- 并发场景隐患:直接调用
last()取最后一条记录,高并发场景下会出现重复生成序列号的问题,生产环境建议加数据库事务或者唯一索引约束
修正后代码
import datetime from django.db import transaction if serialNumberForm.is_valid(): os = serialNumberForm.save(commit=False) # 统一提取公共配置 current_year = datetime.date.today().year # 产品名称缩写增加长度校验,避免下标越界 product_name = product.nome.strip() fix = product_name[3:6] if len(product_name) >=6 else product_name[:2].upper() suffix = Produto.id # 加事务和行锁避免并发重复问题 with transaction.atomic(): lastProduct = NumeroSerie.objects.select_for_update().last() # 无历史记录或跨年时,变量号从初始值101开始 if not lastProduct or int(lastProduct.serialNumber[:4]) != current_year: var = 101 else: # 提取最后3位变量号转数字后自增 last_var = int(lastProduct.serialNumber[-3:]) var = last_var + 1 # 拼接生成最终序列号 os.serialNumber = f"{current_year}{fix}{suffix}{var}" os.save()
补充优化建议
- 建议给
NumeroSerie表的serialNumber字段加唯一索引,避免极端场景下出现重复值 - 产品名称缩写的截取逻辑可根据实际业务调整,上述代码加了长度兜底逻辑,避免产品名过短时报错
- 如果需要固定变量号为3位,不足时前面补0,可以把变量号拼接逻辑改成
f"{var:03d}",超出3位时会自动延长不会截断
内容的提问来源于stack exchange,提问作者Gabriel Reis
相关产品推荐
相关产品推荐

