2011-07-05 24 views
8

Tengo una aplicación de blog simple con el modelo "Publicar". Si elimino todas las entradas en el modelo Post Me aparece un error cuando intento hacer referencia al primer elemento de la lista de entradas por fecha, lo cual hice así:django cómo obtener el 0º artículo de una lista posiblemente vacía

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

El error es: IndexError: índice de la lista fuera de rango

como una solución, ahora consigo el artículo como éste:

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

esto funciona si no hay artículos en mi modelo "post", y no hay excepción. Sin embargo, para mí esto parece demasiado código para hacer algo bastante simple. Supongo que hay una forma mejor de hacerlo utilizando la API django QuerySet, pero no puedo encontrar nada en la documentación.

¿Alguna idea?

EDIT: Extrañamente, esto arroja ningún error cuando no hay elementos en el modelo Post:

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

Respuesta

15

Nada de extraño en ello, es un comportamiento completamente esperado. Una lista vacía (o queryset específicamente en este caso) se evalúa como False para que nunca indexe en el queryset. Mientras que si intenta indexar en una lista vacía (como lo hace con el primer enfoque) arrojará un IndexError.

Lo que ha escrito funcionará, pero no es lo mejor. Una mejor manera de escribir esto sería igual que

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

Esta es una forma más Pythonic de escribirlo y es más fácil de leer y entender lo que está tratando de hacer.

O mejor aún

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

Aviso en este segundo ejemplo que utiliza la última método queryset(). También tenga en cuenta que el argumento es simplemente el nombre de campo y no-nombre de campo. También se puede incluso especificar en sus modelos de clase Meta get_latest_by = 'date_created' y luego la línea se convierte simplemente en latest_post = Post.objects.latest(), incluso sin necesidad de especificar el argumento de nombre de campo

+1

+1 para 'intentar ... excepto'. Es más fácil pedir perdón que permiso. –

+2

+1 por sugerir lo último como una forma aún mejor de resolver el problema. –

+0

Tenga en cuenta que '.latest()' no filtra ninguna entrada nula, y los nulos primero se ordenan normalmente :). Entonces, si las fechas pueden ser nulas, necesita 'Post.objects.exclude (date_created = None) .latest ('date_created')' – rcoup

2

Una solución pitón sencilla sería utilizar en lugar

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] 

Esto no será una excepción y todavía se puede comprobar si hay una condición lista vacía en última publicación.

Su problema surge del uso de un índice absoluto IE: [0] que puede existir o no. Al usar un segmento [: 1] está diciendo que quiere una lista con el primer elemento de la lista, si existe ... si no existe, simplemente obtendrá una lista vacía.

+0

Lo sentimos, respuesta similar dada por la corrección de stefan – Howard

+0

: cuando se usa '[: 1]', if no hay resultados, obtienes una lista vacía ('[]'), no 'None'. –

+0

Corregido el retorno para reflejar el resultado de la lista vacía. – Howard

Cuestiones relacionadas