Model自定义Save方法后如何避免重复保存且仅在创建对象时生效
Django模型自定义save方法仅创建时执行的解决方案
核心实现思路
通过Django模型内置的_state.adding属性判断当前实例是否为首次新增,仅在新增时执行order字段的赋值逻辑,更新操作直接调用父类save方法即可。同时修复你原代码中的语法错误。
方案1:自动区分新增/更新场景(无需修改调用代码)
修改后的模型save方法代码如下:
def save(self, *args, **kwargs): # _state.adding为True代表实例是首次创建,尚未存入数据库 if self._state.adding: model_class = type(self) last_item = model_class.objects.order_by('-order').first() if last_item is not None: # 修复原代码语法错误:赋值语句右侧不能使用+=操作符 self.order = last_item.order + 1 else: # 第一条数据默认order从1开始 self.order = 1 # 无论新增还是更新,最终都调用父类save方法执行入库 super().save(*args, **kwargs)
该方案下,你在View中调用save()更新order字段时,不会触发自定义的order赋值逻辑,完全不会冲突。
方案2:手动控制是否跳过自定义逻辑
如果存在特殊场景需要灵活控制逻辑是否执行,可以给save方法添加自定义参数:
def save(self, *args, **kwargs): # 提取自定义控制参数,默认不跳过逻辑 skip_order_logic = kwargs.pop('skip_order_logic', False) if not skip_order_logic and self._state.adding: model_class = type(self) last_item = model_class.objects.order_by('-order').first() if last_item is not None: self.order = last_item.order + 1 else: self.order = 1 super().save(*args, **kwargs)
需要跳过自定义逻辑时,在调用save方法时传入参数即可:your_order_instance.save(skip_order_logic=True)
额外注意事项
高并发场景下,查询最大order+1的写法可能出现竞争条件,导致多个实例拿到相同的order值,对order唯一性要求高的场景可以给order字段加数据库唯一约束,或者查询时使用select_for_update()加行锁避免冲突。
内容的提问来源于stack exchange,提问作者Elliot13
相关产品推荐
相关产品推荐

