django如何从可能为空的列表中获取第0项

时间:2011-07-05 16:45:43

标签: django django-queryset

我有一个简单的博客应用程序,其模型为“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]

3 个答案:

答案 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],你说你想要一个包含列表中第一项的列表(如果它存在)......如果它不存在,你只需要一个空列表。