Django, как получить 0-й элемент из возможно пустого списка - PullRequest
8 голосов
/ 05 июля 2011

У меня есть простое приложение для блога с моделью «Пост». Если я удаляю все записи в модели поста, я получаю сообщение об ошибке, когда пытаюсь сослаться на первый элемент в списке постов, упорядоченный по дате, что я сделал следующим образом:

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]

Это работает, если в моей модели "Пост" нет элементов и не выдается исключение. Однако мне кажется, что это слишком много кода, чтобы сделать что-то довольно простое. Я предполагаю, что есть лучший способ сделать это с помощью API QuerySet django, но ничего не могу найти в документации.

Есть идеи?

РЕДАКТИРОВАТЬ: странно, это не выдает ошибку, когда нет никаких элементов в модели Post:

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

Ответы [ 3 ]

15 голосов
/ 05 июля 2011

Ничего странного в этом нет, это вполне ожидаемое поведение. Пустой список (или, в частности, набор запросов в этом случае) оценивается как False, поэтому вы никогда не будете индексировать набор запросов. Хотя если вы попытаетесь выполнить индексирование в пустой список (как при первом подходе), он выдаст IndexError.

То, что вы написали, будет работать, но это не самый лучший момент. Лучший способ написать это было бы так:

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 (). Также обратите внимание, что аргумент - это просто имя поля, а не -fieldname. Также вы можете даже указать в своих моделях мета-класс get_latest_by = 'date_created', и тогда строка просто станет latest_post = Post.objects.latest(), даже не указывая аргумент fieldname

2 голосов
/ 05 июля 2011
latest_post = Post.objects.order_by('-date_created')[:1]
if latest_post:
    latest_post = latest_post[0]

Это не вызовет исключения, и вы все равно можете проверить наличие пустого списка в последнем_посте.

Ваша проблема связана с использованием абсолютного индекса IE: [0], который может существовать или не существовать.,Используя фрагмент [: 1], вы говорите, что хотите получить список с первым элементом в списке, если он существует ... если он не существует, вы просто получите пустой список.

2 голосов
/ 05 июля 2011

Простое исправление Python будет использовать вместо

latest_post = Post.objects.order_by('-date_created')[0:1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...