我有一个简单的博客应用程序,其模型为“Post”。如果我删除Post模型中的所有条目,当我尝试引用按日期排序的帖子列表中的第一项时,我会收到错误,我这样做:
latest_post = Post.objects.order_by('-date_created')[0]
错误是:IndexError:列表索引超出范围
作为修复,我现在得到这样的项目:
all_posts = Post.objects.order_by('-date_created')
latest_post = ()
if (all_posts):
latest_post = all_posts[0]
如果我的模型“Post”中没有项目,则无效,并且不会抛出任何异常。 但对我来说,这似乎是太多的代码来做一些相当简单的事情。我假设使用django QuerySet API有更好的方法,但在文档中找不到任何内容。
有什么想法吗?
编辑:奇怪的是,当Post模型中没有项目时,这不会引发错误:
latest_post_list = Post.objects.all().order_by('-date_created')[1:10]
答案 0 :(得分:15)
没有什么奇怪的,这是完全预期的行为。空列表(或在此情况下特别是查询集)的计算结果为False,因此您永远不会索引到查询集。如果您尝试索引到一个空列表(就像您使用第一种方法一样),它将抛出一个IndexError。
你写的东西会起作用,但它不是最好的imo。写这个的更好方法就是这样
try:
latest_post = Post.objects.order_by('-date_created')[0]
except IndexError:
latest_post = None
这是一种更加抒情的写作方式,更容易阅读和理解你想要做的事情。
甚至更好
try:
latest_post = Post.objects.latest('date_created')
except Post.DoesNotExist:
latest_post = None
请注意,在第二个示例中,它使用了latest()queryset方法。另请注意,参数只是fieldname而不是-fieldname。您甚至可以在模型中指定元类get_latest_by = 'date_created'
,然后该行变为latest_post = Post.objects.latest()
,甚至不需要指定fieldname参数
答案 1 :(得分:2)
一个简单的python修复方法是改为使用
latest_post = Post.objects.order_by('-date_created')[0:1]
答案 2 :(得分:2)
latest_post = Post.objects.order_by('-date_created')[:1]
if latest_post:
latest_post = latest_post[0]
这不会引发异常,您仍然可以在latest_post上检查空列表条件。
您的问题源于使用绝对索引IE:[0],可能存在也可能不存在。通过使用切片[:1],你说你想要一个包含列表中第一项的列表(如果它存在)......如果它不存在,你只需要一个空列表。