2011-07-05 10 views
8

Mam prostą aplikację bloga z modelem "Post". Jeśli mogę usunąć wszystkie wpisy w modelu post pojawia się błąd, gdy próbuję odwołać pierwszą pozycję na liście po uporządkowanej według daty, które zrobiłem tak:django jak zdobyć 0 pozycję z możliwie pustej listy

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

Błąd jest: IndexError: Index Lista poza zasięgiem

jako poprawka, teraz uzyskać pozycję tak:

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

to działa, jeśli nie ma żadnych przedmiotów w moim modelu „post”, i nie jest wyjątek. Jednak dla mnie wydaje się, że zbyt wiele kodu, aby zrobić coś dość proste. Zakładam, że jest lepszy sposób na to, używając interfejsu API derygo QuerySet, ale nie można znaleźć niczego w dokumentacji.

Wszelkie pomysły?

EDIT: O dziwo, ten wyrzuca żadnego błędu, gdy nie ma żadnych przedmiotów w modelu post:

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

Odpowiedz

15

nic dziwnego, że to całkowicie oczekiwane zachowanie. Pusta lista (lub konkretnie w tym przypadku zestaw zapytań) zwraca wartość False, więc nigdy nie indeksujesz zapytania. Podczas próby indeksowania do pustej listy (tak jak w przypadku pierwszego podejścia) spowoduje to wywołanie IndexError.

To, co napisałeś, zadziała, ale nie jest najlepsze. Lepszym sposobem napisać to byłoby jak tak

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

Jest to bardziej pythonic sposobem pisania i jest łatwiejszy do odczytania i zrozumienia, co próbujesz zrobić.

Albo jeszcze lepiej

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

Wskazówki w tym drugim przykładzie, że korzysta z najnowszych() metoda queryset. Zauważ także, że argumentem jest po prostu nazwa pola, a nie nazwa pola. Ponadto można nawet określić w swoich modelach Meta klasy get_latest_by = 'date_created' a następnie linia staje się po prostu latest_post = Post.objects.latest() nawet bez konieczności określić argument FieldName

+1

+1 dla "try ... except". Łatwiej jest prosić o przebaczenie niż pozwolenie. –

+2

+1 za sugerowanie najnowszego jako jeszcze lepszego sposobu rozwiązania problemu. –

+0

Zauważ, że '.latest()' nie odfiltrowuje żadnych pustych wpisów - i wartości null sortują najpierw normalnie :). Więc jeśli daty mogą być zerowe, potrzebujesz 'Post.objects.exclude (date_created = None) .latest ('date_created')' – rcoup

2

Proste python fix byłoby zamiast używać

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

To nie wyjątek i nadal można sprawdzić dla pustej listy stanu na najnowszy post.

Twój problem wynika z użycia bezwzględnego indeksu IE: [0], który może ale nie musi istnieć. Używając plasterka [: 1] mówisz, że chcesz listę z pierwszym elementem na liście, jeśli istnieje ... jeśli nie istnieje, po prostu otrzymasz pustą listę.

+0

Przepraszamy, podobna odpowiedź udzielona przez stefan – Howard

+0

korekta: przy użyciu '[: 1]', jeśli nie ma wyników, otrzymujesz pustą listę ('[]'), a nie 'Brak'. –

+0

Poprawiono powrót do odzwierciedlenia pustego wyniku listy. – Howard

Powiązane problemy