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

已捕获DoesNotExist仍报错?Django外键查询异常求助

为什么捕获了TestModel_2.DoesNotExist仍触发该异常?

我在Django项目里明明用try-except捕获了TestModel_2.DoesNotExist异常,但运行时还是抛出了renoauth.models.DoesNotExist: TestModel_2 matching query does not exist错误,相关代码和报错堆栈如下:

相关代码片段

views.py 中的代码

try: 
    testmodel2 = TestModel_2.objects.get(description='a')
except TestModel_2.DoesNotExist: 
    testmodel2 = None

models.py 中的模型定义

@python_2_unicode_compatible
class TestModel_2(models.Model):
    description = models.CharField(max_length=34)
    created = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return "TestModel %s" % self.description

@python_2_unicode_compatible
class TestModelLog_2(models.Model):
    description = models.CharField(max_length=34)
    test_foreignkey = models.ForeignKey(TestModel_2, related_name='test_foreignkey_1', null=True, blank=True, on_delete=models.DO_NOTHING)
    test_foreignkey_2 = models.ForeignKey(TestModel_2, related_name='test_foreignkey_2', null=True, blank=True, on_delete=models.DO_NOTHING)

报错堆栈信息

Internal Server Error: /accounts/test2/
Traceback (most recent call last):
  File "D:\pythonDev\interpreters\interpreter1\lib\site-packages\django\db\models\fields\related_descriptors.py", line 170, in __get__
    rel_obj = getattr(instance, self.cache_name)
AttributeError: 'TestModelLog_2' object has no attribute '_test_foreignkey_2_cache'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "D:\pythonDev\interpreters\interpreter1\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
    response = get_response(request)
  File "D:\pythonDev\interpreters\interpreter1\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "D:\pythonDev\interpreters\interpreter1\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "D:\pythonDev\project\logintest\renoauth\views.py", line 56, in test2
    if testmodel_2_log.test_foreignkey_2 is None:
  File "D:\pythonDev\interpreters\interpreter1\lib\site-packages\django\db\models\fields\related_descriptors.py", line 179, in __get__
    rel_obj = qs.get()
  File "D:\pythonDev\interpreters\interpreter1\lib\site-packages\django\db\models\query.py", line 385, in get
    self.model._meta.object_name
renoauth.models.DoesNotExist: TestModel_2 matching query does not exist.
[06/Jan/2018 16:20:24] "POST /accounts/test2/ HTTP/1.1" 500 15678

问题出在哪?

你仔细看报错堆栈的关键行:if testmodel_2_log.test_foreignkey_2 is None:——这个异常根本不是来自你写的那个try-except块,而是在你访问TestModelLog_2实例的test_foreignkey_2属性时触发的。

为什么会这样?因为你给外键设置了null=True, blank=True,但用了on_delete=models.DO_NOTHING。这就意味着,如果数据库里某个TestModel_2记录被删了,关联的TestModelLog_2的test_foreignkey_2_id字段还保留着那个已删除的ID,变成了无效关联。

当你访问testmodel_2_log.test_foreignkey_2时,Django会自动去数据库查找对应的TestModel_2实例,找不到就抛出DoesNotExist异常,而这个操作完全在你之前的try-except范围之外,所以错误就冒出来了。

怎么解决?

这里给你几个实用的方案:

方案一:在访问外键时捕获异常

直接在你检查test_foreignkey_2的地方加try-except:

try:
    related_model = testmodel_2_log.test_foreignkey_2
except TestModel_2.DoesNotExist:
    related_model = None
if related_model is None:
    # 你的业务逻辑

方案二:直接检查外键ID字段(更高效)

Django的外键字段会自动生成对应的xxx_id字段,你可以直接检查这个字段是否为None,这样不会触发数据库查询,避免异常:

if testmodel_2_log.test_foreignkey_2_id is None:
    # 你的业务逻辑

方案三:修复数据+修改on_delete策略

先清理数据库里的无效关联:找到所有test_foreignkey_2_id对应的TestModel_2不存在的TestModelLog_2记录,把test_foreignkey_2_id设为NULL。

然后修改外键的on_delete为SET_NULL,这样以后删除TestModel_2时,关联的TestModelLog_2外键会自动设为NULL,从根源避免无效关联:

test_foreignkey_2 = models.ForeignKey(
    TestModel_2, 
    related_name='test_foreignkey_2', 
    null=True, 
    blank=True, 
    on_delete=models.SET_NULL  # 把DO_NOTHING改成SET_NULL
)

内容的提问来源于stack exchange,提问作者David Foie Gras

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:29:22