重写Django模型Save方法实现主键步长为5自增失败求助
问题分析与修复方案
你的代码存在几个关键错误,导致无法正常创建客户端条目,以下是问题点和修复方案:
核心错误点
- 模型管理器拼写错误:
Client.object应为Client.objects(Django模型默认数据管理器是objects,末尾缺少s) - 字段赋值错误:else分支错误给不存在的
self.client赋值,实际应给主键字段self.client_id赋值 - 更新逻辑缺失:仅在创建新对象时执行保存,更新现有对象时完全跳过了
save逻辑 - 异常处理不合理:捕获过于宽泛的异常类型且直接返回
False,掩盖了真实错误,同时不符合Djangosave()方法的无返回值设计
修复后的代码
from django.db import models class Client(models.Model): client_id = models.PositiveIntegerField(primary_key=True) client_name = models.CharField(max_length=1000, null=True, blank=True) def save(self, *args, **kwargs): if self._state.adding: # 生成自增5的主键 if not Client.objects.exists(): self.client_id = 5 else: # 显式按主键排序,确保拿到最大的ID last_client = Client.objects.order_by('client_id').last() self.client_id = last_client.client_id + 5 # 无论创建还是更新,都执行父类的保存逻辑 super().save(*args, **kwargs) def __str__(self): return str(self.client_name) class Meta: db_table = 'Client'
额外优化建议
如果你的服务存在高并发创建场景,上述代码可能出现竞态条件(多个请求同时生成相同client_id),可以通过数据库事务加锁解决:
from django.db import models, transaction class Client(models.Model): # 字段定义不变 client_id = models.PositiveIntegerField(primary_key=True) client_name = models.CharField(max_length=1000, null=True, blank=True) def save(self, *args, **kwargs): if self._state.adding: with transaction.atomic(): # 锁定表防止并发写入冲突 Client.objects.select_for_update().all() if not Client.objects.exists(): self.client_id = 5 else: last_client = Client.objects.order_by('client_id').last() self.client_id = last_client.client_id + 5 super().save(*args, **kwargs) # __str__和Meta类不变
内容的提问来源于stack exchange,提问作者DjangoRulz
相关产品推荐
相关产品推荐

