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

Django的save()函数是否覆盖数据库旧数据及写入重复问题处理

问题根因分析

你遇到的旧数据被覆盖问题核心是模型字段定义存在逻辑冲突:

  • 你将TRAN_TYPE设为了单字段主键,Django的save()默认逻辑为:如果模型实例的主键字段有值,就执行UPDATE操作更新对应主键的已有记录,只有主键为空时才会执行INSERT新增记录。哪怕你设置了TIME_UPDATED+TRAN_TYPE的联合唯一约束,也会被单字段主键的判断逻辑覆盖,因此只要TRAN_TYPE相同,不管时间如何变化,都会覆盖旧记录。
  • 你设置的联合唯一约束和单主键定义本身是矛盾的:主键已经保证TRAN_TYPE全局唯一,联合唯一约束完全不会生效。
修复方案

第一步:调整模型字段定义

删除TRAN_TYPE的主键声明,新增独立的自增主键,保留联合唯一约束即可,修改后的模型如下:

class Transactions(models.Model):
    # 新增自增ID作为主键,也可以省略该行,Django默认会自动创建id主键字段
    id = models.AutoField(primary_key=True)
    class Meta:
        db_table='TRANSACTIONS'
        unique_together=(("TIME_UPDATED","TRAN_TYPE",),)
        indexes=[
        models.Index(fields=["TIME_UPDATED","TRAN_TYPE"]),
        models.Index(fields=["TRAN_TYPE"])
        ]
    TIME_UPDATED            =   models.DateTimeField()
    # 删除此处的primary_key=True参数
    TRAN_TYPE               =   models.CharField(max_length=32)
    SUCCESS                 =   models.IntegerField()
    TECHNICAL_DECLINES      =   models.IntegerField()
    BUSINESS_DECLINES       =   models.IntegerField()
    TOTAL                   =   models.IntegerField()
    PERCENTAGE_TECH_DEC     =   models.FloatField()
    def __str__(self):
        return self.TRAN_TYPE
    # 补充args和kwargs参数传递,避免后续调用save时报错
    def save(self,D,tran, *args, **kwargs):
        self.TIME_UPDATED=D
        self.TRAN_TYPE=T=tran['Type']
        self.SUCCESS=S=int(tran['Success'])
        self.TECHNICAL_DECLINES=TD=int(tran['Tech_dec'])
        self.BUSINESS_DECLINES=BD=int(tran['Bus_dec'])
        self.TOTAL=total=S+TD+BD
        if total==0:# 避免除零报错
            self.PERCENTAGE_TECH_DEC=0
        else:
            self.PERCENTAGE_TECH_DEC=((TD/(total))*100)
        super(Transactions,self).save(*args, **kwargs)

第二步:更新数据库表结构

修改完模型后执行makemigrations和migrate命令同步表结构,操作前请先备份存量数据避免丢失。

第三步:可选异常处理优化

如果需要避免重复插入相同时间+相同交易类型的记录,可以在调用save时添加force_insert=True参数强制走插入逻辑,一旦触发联合唯一约束会抛出IntegrityError,你可以捕获该异常做对应处理:

# 调用示例
from django.db import IntegrityError

try:
    tran_obj = Transactions()
    tran_obj.save(D=current_time, tran=raw_data, force_insert=True)
except IntegrityError:
    # 重复数据处理逻辑,比如打日志、跳过该条记录
    print(f"时间{current_time}的{raw_data['Type']}交易数据已存在,跳过插入")

调整完成后,相同交易类型、不同时间点的数据都会作为新记录插入,不会再覆盖旧数据,同时联合唯一约束会避免同一时间点重复插入相同交易类型的数据,符合你存储全量历史数据的需求。

内容的提问来源于stack exchange,提问作者Shankz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 09:15:00