You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:55:50