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

时间:2021-10-22 22:52:30

I have a simple blog app with the model "Post". If I delete all the entries in the Post model I get an error when I try reference the first item in the post list ordered by date, which I did like this:

我有一个简单的博客应用程序与模型“发布”。如果我删除Post模型中的所有条目,当我尝试引用按日期排序的帖子列表中的第一项时,我会收到错误,我这样做:

latest_post = Post.objects.order_by('-date_created')[0]

The error is: IndexError: list index out of range

错误是:IndexError:列表索引超出范围

As a fix, I now get the item like this:

作为修复,我现在得到这样的项目:

all_posts = Post.objects.order_by('-date_created')
latest_post = ()
if (all_posts):
  latest_post = all_posts[0]

This works if there are no items in my model "Post", and no exception is thrown. However to me this seems like too much code to do something fairly simple. I assume there is a better way to do this using the django QuerySet API, but can't find anything in the documentation.

如果我的模型“Post”中没有项目,并且没有抛出异常,则此方法有效。但对我来说,这似乎是太多的代码来做一些相当简单的事情。我假设使用django QuerySet API有更好的方法,但在文档中找不到任何内容。

Any ideas?

有任何想法吗?

EDIT: Strangely, this throws no error when there are no items in the Post model:

编辑:奇怪的是,当Post模型中没有项目时,这不会引发错误:

latest_post_list = Post.objects.all().order_by('-date_created')[1:10]

3 个解决方案

#1


15  

Nothing strange about that, it's completely expected behavior. An empty list (or queryset specifically in this case) evaluates to False so you never index into the queryset. While if you try to index into an empty list (like you do with the first approach) it will throw an IndexError.

没有什么奇怪的,这是完全预期的行为。空列表(或在此情况下特别是查询集)的计算结果为False,因此您永远不会索引到查询集。如果您尝试索引到一个空列表(就像您使用第一种方法一样),它将抛出一个IndexError。

What you've written will work, but it's not the best imo. A better way to write this would be like so

你写的东西会起作用,但它不是最好的imo。写这个的更好方法就是这样

try:
    latest_post = Post.objects.order_by('-date_created')[0]
except IndexError:
    latest_post = None

This is a more pythonic way of writing it and is easier to read and understand what you're trying to do.

这是一种更加pythonic的写作方式,更容易阅读和理解你想要做的事情。

Or even better

甚至更好

try:
    latest_post = Post.objects.latest('date_created')
except Post.DoesNotExist:
    latest_post = None

Notice in this second example that it uses the latest() queryset method. Also note that the argument is simply the fieldname and not -fieldname. Also you can even specify in your models Meta class get_latest_by = 'date_created' and then the line simply becomes latest_post = Post.objects.latest() without even needing to specify the fieldname argument

请注意,在第二个示例中,它使用了latest()queryset方法。另请注意,参数只是fieldname而不是-fieldname。你甚至可以在你的模型中指定元类get_latest_by ='date_created',然后该行简单地变为latest_post = Post.objects.latest(),甚至不需要指定fieldname参数

#2


2  

A simple python fix would be to instead use

一个简单的python修复将改为使用

latest_post = Post.objects.order_by('-date_created')[0:1]

#3


2  

latest_post = Post.objects.order_by('-date_created')[:1]
if latest_post:
    latest_post = latest_post[0]

This will not throw an exception and you can still check for a empty list condition on latest_post.

这不会引发异常,您仍然可以在latest_post上检查空列表条件。

Your problem arises from using an absolute index IE: [0] which may or may not exist. By using a slice [:1] you are saying you want a list with the first item in the list if it exists... if it doesn't exist you will simply get an empty list.

您的问题来自使用绝对索引IE:[0],可能存在也可能不存在。通过使用切片[:1],您说您希望列表中包含列表中的第一项(如果它存在)...如果它不存在,您只需获得一个空列表。

#1


15  

Nothing strange about that, it's completely expected behavior. An empty list (or queryset specifically in this case) evaluates to False so you never index into the queryset. While if you try to index into an empty list (like you do with the first approach) it will throw an IndexError.

没有什么奇怪的,这是完全预期的行为。空列表(或在此情况下特别是查询集)的计算结果为False,因此您永远不会索引到查询集。如果您尝试索引到一个空列表(就像您使用第一种方法一样),它将抛出一个IndexError。

What you've written will work, but it's not the best imo. A better way to write this would be like so

你写的东西会起作用,但它不是最好的imo。写这个的更好方法就是这样

try:
    latest_post = Post.objects.order_by('-date_created')[0]
except IndexError:
    latest_post = None

This is a more pythonic way of writing it and is easier to read and understand what you're trying to do.

这是一种更加pythonic的写作方式,更容易阅读和理解你想要做的事情。

Or even better

甚至更好

try:
    latest_post = Post.objects.latest('date_created')
except Post.DoesNotExist:
    latest_post = None

Notice in this second example that it uses the latest() queryset method. Also note that the argument is simply the fieldname and not -fieldname. Also you can even specify in your models Meta class get_latest_by = 'date_created' and then the line simply becomes latest_post = Post.objects.latest() without even needing to specify the fieldname argument

请注意,在第二个示例中,它使用了latest()queryset方法。另请注意,参数只是fieldname而不是-fieldname。你甚至可以在你的模型中指定元类get_latest_by ='date_created',然后该行简单地变为latest_post = Post.objects.latest(),甚至不需要指定fieldname参数

#2


2  

A simple python fix would be to instead use

一个简单的python修复将改为使用

latest_post = Post.objects.order_by('-date_created')[0:1]

#3


2  

latest_post = Post.objects.order_by('-date_created')[:1]
if latest_post:
    latest_post = latest_post[0]

This will not throw an exception and you can still check for a empty list condition on latest_post.

这不会引发异常,您仍然可以在latest_post上检查空列表条件。

Your problem arises from using an absolute index IE: [0] which may or may not exist. By using a slice [:1] you are saying you want a list with the first item in the list if it exists... if it doesn't exist you will simply get an empty list.

您的问题来自使用绝对索引IE:[0],可能存在也可能不存在。通过使用切片[:1],您说您希望列表中包含列表中的第一项(如果它存在)...如果它不存在,您只需获得一个空列表。