Django中实现存在则累加更新、不存在则创建记录的问题
Django实现“存在则累加更新,不存在则插入”的解决方案
你遇到的问题其实是对get_or_create的使用场景没抓准——它的核心是根据指定查询条件获取或创建对象,但如果要在获取后做字段累加更新,需要额外处理;更关键的是,如果你的查询条件没写对(比如没把label作为唯一匹配依据),就会重复生成新行。下面给你两种靠谱的解决方案:
方法1:用Django内置的update_or_create(首推)
这是Django专门为“存在则更新、不存在则创建”场景设计的API,而且是原子操作,能避免并发场景下的数据不一致问题。
先假设你的模型定义是这样的(注意给label加唯一约束,确保它能唯一标识一条记录):
class AprilSales(models.Model): label = models.CharField(max_length=100, unique=True) sold = models.IntegerField(default=0)
实现需求的代码非常简洁:
product = "你的产品名称" add_sold = 10 # 要新增的销量数值 # update_or_create会先按kwargs查询,找到就更新defaults里的字段,找不到就创建 obj, created = AprilSales.objects.update_or_create( label=product, # 核心:用label作为唯一查询条件 defaults={ # 用F表达式让数据库直接做累加,避免并发下的数值错误 'sold': models.F('sold') + add_sold } )
重点提醒:
- 一定要确保
label是唯一查询条件,最好给模型的label字段加unique=True约束,否则如果数据库里有多个相同label的记录,update_or_create只会更新第一条匹配的,或者在查询不到时创建新行。 - 使用
models.F是为了让累加操作直接在数据库层面完成,避免先查询再更新导致的并发问题(比如两个请求同时读取同一个sold值,各自加完再保存,最终结果会少加一次)。
方法2:手动用get_or_create处理(不推荐,仅作参考)
如果你一定要用get_or_create,可以结合事务来实现,但复杂度比update_or_create高,而且要注意并发问题:
from django.db import transaction product = "你的产品名称" add_sold = 10 try: # 用事务包裹,确保查询和更新是原子操作 with transaction.atomic(): obj = AprilSales.objects.get(label=product) obj.sold += add_sold obj.save() except AprilSales.DoesNotExist: obj = AprilSales.objects.create(label=product, sold=add_sold)
这种方式建议给label加唯一约束,否则高并发场景下可能出现两个请求同时进入DoesNotExist分支,创建两条相同label的记录。
为什么你之前的get_or_create总是生成新行?
大概率是你调用get_or_create时没把label作为查询条件,或者查询条件错误。比如如果你的代码是这样的:
# 错误示例:用sold作为查询条件,每次sold不同都会创建新行 obj, created = AprilSales.objects.get_or_create(sold=add_sold, defaults={'label': product})
这种写法完全偏离了需求,自然会每次都生成新行。
内容的提问来源于stack exchange,提问作者carcara makoto
相关产品推荐
相关产品推荐

