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

Django中操作数据时异常导致数据行被删除问题求助

排查Django操作异常时数据行被删除的问题

这个问题我之前帮同事排查过几乎一模一样的情况——你换了PostgreSQL和SQLite都复现,说明根本和数据库类型无关,问题肯定出在你的Django代码逻辑里,大概率是异常处理分支的误操作或者事务/信号逻辑的疏漏,给你拆解几个常见原因和排查步骤:

最常见的坑:异常分支里的误删除代码

很多人在写try-except块时,会不小心在异常处理里加了delete()调用,比如复制粘贴代码时没改全:

def update_some_data(request, obj_id):
    try:
        obj = MyModel.objects.get(id=obj_id)
        # 这里的操作触发异常,比如字段验证失败、关联数据不存在
        obj.some_field = invalid_value
        obj.save()
    except Exception as e:
        # 本来想打日志或者返回错误,结果不小心留了删除代码
        obj.delete()
        return JsonResponse({"error": str(e)})

只要操作触发异常,就会执行obj.delete(),直接删掉数据库里的行。先把所有涉及该模型操作的try-except块扫一遍,90%的概率是这个问题。

信号处理器里的异常触发删除

如果你的模型注册了pre_save、post_save这类信号,有没有可能信号处理器里的逻辑在异常场景下触发了删除?比如:

from django.db.models.signals import pre_save
from django.dispatch import receiver

@receiver(pre_save, sender=MyModel)
def my_model_pre_save(sender, instance, **kwargs):
    try:
        # 这里的操作抛出异常
        validate_something(instance)
    except ValidationError:
        # 错误地删除了实例
        instance.delete()

这种情况下,只要信号里的校验失败,就会删除当前要操作的实例,而且因为信号是隐式执行的,很容易被忽略。

事务逻辑的错误处理

Django 1.9默认对每个请求开启事务(数据库支持的话),如果你用了transaction.atomic(),捕获异常后如果对实例执行写操作(包括删除),就会绕过事务回滚直接修改数据库:

from django.db import transaction

def process_data(request):
    try:
        with transaction.atomic():
            obj = MyModel.objects.get(id=1)
            obj.some_field = invalid_value
            obj.save()  # 这里抛出异常,事务会回滚
    except Exception as e:
        # 事务回滚后,obj还是内存中的实例,此时调用delete()会直接删除数据库里的真实数据
        obj.delete()

因为atomic()块里的异常会回滚所有操作,但你在块外获取的obj还是指向数据库里的真实行,此时执行删除就会真的删掉。

排查利器:开启SQL日志

如果上面的排查都没找到问题,直接开启Django的SQL日志,看异常发生时到底执行了哪些SQL语句,一眼就能看到DELETE语句的来源。在settings.py里添加:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'level': 'DEBUG',
            'handlers': ['console'],
        },
    },
}

运行代码触发异常后,控制台会打印所有执行的SQL,找到那条DELETE语句,就能反推是哪段代码触发的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:05:41