【发布时间】:2011-05-20 04:24:18
【问题描述】:
每当我这样做时:
thepost = Content.objects.get(name="test")
当什么都没找到时它总是抛出一个错误。 我该如何处理?
【问题讨论】:
-
这就是它应该工作的方式。你有什么问题?如何编写
try语句?
每当我这样做时:
thepost = Content.objects.get(name="test")
当什么都没找到时它总是抛出一个错误。 我该如何处理?
【问题讨论】:
try 语句?
try:
thepost = Content.objects.get(name="test")
except Content.DoesNotExist:
thepost = None
使用模型DoesNotExist异常
【讨论】:
Content.DoesNotExist,如果您想在找不到对象的情况下继续(即不像我的示例中那样抛出404错误),此代码结构很有用。
通常情况下,直接使用 Django 快捷函数get_object_or_404 代替 API 会更有用:
from django.shortcuts import get_object_or_404
thepost = get_object_or_404(Content, name='test')
很明显,如果找不到对象,这将引发 404 错误,如果成功,您的代码将继续。
【讨论】:
捕获异常
try:
thepost = Content.objects.get(name="test")
except Content.DoesNotExist:
thepost = None
或者您可以过滤,如果没有匹配项,它将返回一个空列表
posts = Content.objects.filter(name="test")
if posts:
# do something with posts[0] and see if you want to raise error if post > 1
【讨论】:
for plugin in plugins; try; processed_text = plugin.process(text) ; except Exception1,: do something Exception 2; do something 没有更简单的替代方法,在这种特定情况下,它绝对是完美的,您会在访问 item 之前执行 dict.has_key 还是仅访问 item 并捕获 KeyError?
您还可以捕获一个通用的 DoesNotExist。根据http://docs.djangoproject.com/en/dev/ref/models/querysets/的文档
from django.core.exceptions import ObjectDoesNotExist
try:
e = Entry.objects.get(id=3)
b = Blog.objects.get(id=1)
except ObjectDoesNotExist:
print "Either the entry or blog doesn't exist."
【讨论】:
提出Http404 exception 效果很好:
from django.http import Http404
def detail(request, poll_id):
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404
return render_to_response('polls/detail.html', {'poll': p})
【讨论】:
在视图的不同点处理异常可能真的很麻烦..在 models.py 文件中定义自定义模型管理器怎么样,比如
class ContentManager(model.Manager):
def get_nicely(self, **kwargs):
try:
return self.get(kwargs)
except(KeyError, Content.DoesNotExist):
return None
然后将其包含在内容模型类中
class Content(model.Model):
...
objects = ContentManager()
通过这种方式可以很容易地在视图中处理,即
post = Content.objects.get_nicely(pk = 1)
if post != None:
# Do something
else:
# This post doesn't exist
【讨论】:
另一种写法:
try:
thepost = Content.objects.get(name="test")
except Content.DoesNotExist:
thepost = None
很简单:
thepost = Content.objects.filter(name="test").first()
请注意,两者并不完全相同。管理器方法get 不仅会在您查询的没有记录的情况下引发异常,而且在找到多条记录时也会引发异常。当有多个记录时使用 first 可能会通过返回第一条记录以静默方式使您的业务逻辑失败。
【讨论】:
.get 而不是 .first 几乎总是更好,因为正如您所说,它可能会导致意想不到的结果。我唯一一次使用.first 是如果我使用通用外键并进行验证以确保最多只有一项。
基本上有两种方法可以做到这一点。第一种方法更冗长,因为它不使用任何shortcuts:
from django.http import Http404
from .models import Content
try:
thepost = Content.objects.get(name="test")
except Content.DoesNotExist:
raise Http404("Content does not exist")
现在由于这种操作(即获取一个对象或如果它不存在则引发 404)在 Web 开发中相当普遍,Django 提供了一个名为 get_object_or_404 的快捷方式,它将 get() 请求的对象或引发 @987654327 @以防万一找不到:
from django.shortcuts import get_object_or_404
from .models import Content
thepost = get_object_or_404(Content, name="test")
同样对于对象列表,您可以使用get_list_or_404() 函数,该函数利用filter() 而不是get(),如果返回的列表为空,Http404 将被提升。
【讨论】: