Django错误 - 匹配的查询不存在。

155

我最近将我的项目发布到生产级别,但突然间我遇到了一些在开发阶段从未遇到过的问题。

当用户提交某些操作时,有时会出现以下错误。

Traceback (most recent call last):

  File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 111, in get_response
    response = callback(request, *callback_args, **callback_kwargs)

  File "home/ubuntu/server/opineer/comments/views.py", line 103, in comment_expand
    comment = Comment.objects.get(pk=comment_id)

  File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 131, in get
    return self.get_query_set().get(*args, **kwargs)

  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 366, in get
    % self.model._meta.object_name)

DoesNotExist: Comment matching query does not exist

真正让我沮丧的是该项目在本地环境中很好地工作,而且匹配的查询对象确实存在于数据库中。

现在我怀疑用户正在访问被其他用户保留的数据库,但没有办法证明我的观点,也没有任何解决办法。

有人遇到过这种问题吗?有什么建议可以解决这个问题吗?

非常感谢您提前的帮助。

编辑:我已经使用从服务器错误电子邮件中检索的相同信息手动查询了数据库。 我能够毫无问题地访问该条目。 此外,似乎用户执行的完全相同行为并不会大部分时间引起任何问题,而只会在一些情况下(尚不清楚)引起问题。 总之,这绝对不是与数据库中缺少条目有关的问题。


2
很明显,这是一个数据问题:comment = Comment.objects.get(pk=comment_id) 需要验证该ID在数据库中是否存在。 - karthikr
4
"python manage.py sqlall"命令将生成与您的模型相对应的SQL语句。请检查它是否与DB schema SQL匹配。例如,如果使用PostgreSQL,则可能还涉及序列的问题。总之,您能否提供有关您的环境(SQDB、数据库、数据库中的相应表以及models.py中的代码等)的更多信息? - Ricola3D
@Ricola3D 你好,我目前正在使用Amazon EC2实例托管MySql数据库。而且我暂时使用内置的Django评论功能。同时,我会尝试运行你建议的sqlall命令。谢谢。 - Chris P
8个回答

180

也许您没有这个主键的评论记录,那么您应该使用这段代码:

try:
    comment = Comment.objects.get(pk=comment_id)
except Comment.DoesNotExist:
    comment = None

6
在这种情况下,最好的选择是捕获错误并显示一个精心预配置的消息,而不是向用户返回404错误。这样可以避免任何不必要的困扰。 - Love Putin Not War
这段程序代码应该如何运作?def previous_job(self): return self.get_previous_by_start_dt(brand=self.brand, status='finished') or None 不知道如何在此处实现try catch。 - snh_nl
很好的回答。我的使用情况是有导航按钮,用于上一个和下一个零件号记录。但是,有时候会跳过一个零件号。捕获这个错误并返回“None”是完美的解决方案。 - Carewen

146

引发错误的代码行在这里:

comment = Comment.objects.get(pk=comment_id)

您尝试访问不存在的评论。

from django.shortcuts import get_object_or_404

comment = get_object_or_404(Comment, pk=comment_id)

与其在服务器上出现错误,你的用户会得到一个404,表示试图访问不存在的资源。

到目前为止,我想你应该已经意识到这一点了。

有些用户(我自己也是其中之一)会让标签页长时间运行,如果用户有权限删除数据,这可能会发生。404错误可能比向管理员发送电子邮件更好地处理已删除资源错误。

其他用户会从他们的历史记录中访问地址(如果数据已被删除,则仍可能发生)。


3
在长时间运行的选项卡上点个赞。我经常会在旧选项卡上遇到404错误。 - Yuji 'Tomita' Tomita
感谢Chris的建议。真正困扰我的是,当我手动查询MySql数据库时(使用我从服务器收到的错误信息),我可以毫无问题地找到正确的条目。此外,相同的操作有时会引发“DoesNotExist”异常,但大多数情况下都能正常工作。这似乎不是数据库中缺少条目的问题 :( - Chris P
@christophe31 所以我还没有真正实现任何类型的数据库性能优化,也没有采用诸如从库/主库集群或查询缓存等备份方法。我想我会实现这些功能,看看问题是否仍然存在。 - Chris P
我认为这可能是问题的根源,而不是可能的解决方案^^。由于您无法重现错误,我建议采用一个愚蠢的解决方案。尝试捕获错误,在catch中等待一秒钟并记录日志后重新获取。 - christophe31
2
另外,您可以在catch中添加以下内容:from django.db import connectionconnection.connection.close()connection.connection = None,尝试重置数据库连接并重新开始。 - christophe31
显示剩余3条评论

36

你可以使用这个:

comment = Comment.objects.filter(pk=comment_id)

如果你想要特定的对象,那么你不能使用过滤器,因为如果查询不匹配,它可能会返回空列表。当它匹配时,你必须从列表中使用第一个对象。 - Jay Modi
4
大概这就是重点所在:使用过滤器并测试结果是否有零或一个条目,而不是生成异常? - Mike 'Pomax' Kamermans
值得注意的是,Model.objects.filter将返回一个Queryset,而Model.objects.get将返回一个对象。如果该对象不存在,则前者将返回一个空的Queryset,而后者将导致Model.DoesNotExist错误。 - ron_g
7
如果未找到记录,Comment.objects.filter(pk=comment_id).first() 将返回 None - steezeburger

18

你可以尝试这种方法。只需使用一个函数来获取你的对象。

def get_object(self, id):
    try:
        return Comment.objects.get(pk=id)
    except Comment.DoesNotExist:
        return False

0

我认为问题在于在开发服务器上传递了一些数据,这些数据不会迁移到生产服务器。

最简单的方法是在生产数据库中定位这些依赖项并提供它们。


有些情况下,直到为时已晚才会知道依赖关系。我来举个例子。我正在建立一个数字图书馆,在详细视图中显示上一条和下一条记录导航按钮(为了方便阅读)。99%的时间,用户希望输入前后两个部件编号,但有时他们可能无法这样做。因此,必须有一种方法来防止错误发生。在我的情况下,try/except逻辑非常理想。前两个答案很好地回答了问题。 - Carewen
我完全同意,最佳实践是始终准备处理这样的错误,“尝试和捕获”正是做到这一点的好方法。我的评论只是关于处理错误原因的。 - Leodarkseid

0

虽然与你的问题无关,但是作为补充,为了避免出现这个错误,你可以增加单元测试的数量并将你的应用程序Docker化。


目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community
如果与编程无关,请不要将其作为答案发布。这个解决方案与他们所询问的完全无关。 - shoebob

-2
comment = Comment.objects.get(pk=comment_id) if Comment.objects.filter(pk=comment_id).exists() else None

1
目前你的回答不够清晰,请[编辑]以添加更多细节,帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community
这会导致额外的数据库查询,可能会快速增加资源使用量。 - djangomachine

-3

试试这个

comment, created = Comment.objects.get_or_create(pk=comment_id)

3
问者不需要创建评论。 - Nwawel A Iroume
确实。如果您基于某个条件查询记录,而该条件未满足,则假设添加记录可能根本不合适。前两个答案已经很好地回答了这个问题。 - Carewen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接