2009-12-14 12 views
9

Gracias a una pista muy útil desde otra pregunta Aprendí que puedo limitar la cantidad de valores de una lista por corte en la plantilla como tal:Django plantilla de la rebanada - Invertir Orden de

{% for comment in thread.comment_set.all|slice:":3" %} 

Ahora me gustaría para obtener los 3 últimos resultados de mis comentarios así que pensé un simple ": -3" o "-3" haría el truco, por desgracia:

Caught an exception while rendering: Negative indexing is not supported. 

también usando:

{% for comment in thread.comment_set.all|slice:":3" reversed %} 

No funciona, porque si tengo 5 comentarios, en lugar de 1,2,3 muestra los primeros tres en 3,2,1 orden.

¿Hay alguna manera en que pueda mostrar los últimos 3 comentarios de una publicación sin tener que ingresar a mi base de datos? Me encantaría poder hacer esto simplemente usando el sistema de plantillas.

SOLUCIÓN

{% for comment in thread.comment_set.all|dictsortreversed:"created"|slice:"3" %} 

Muestra los últimos tres gracias a mi mesa con la fecha y hora de crear.

Respuesta

11

consultas de bases de datos de Django se evalúan con pereza, por lo que el resultado de thread.comment_set.all es un QuerySet no una lista Un QuerySet admite muchas funciones tipo lista, pero no un corte negativo, por lo que el error de indexación no proviene del filtro de plantilla. (Si tiene curiosidad, las divisiones en los objetos QuerySet se traducen en una cláusula limit en la declaración SQL, por lo que no puede usar un número negativo).

En general, Django fomenta un desacoplamiento estricto de plantillas y modelos; El módulo views.py es el adhesivo donde se realiza cualquier trabajo que requiera el conocimiento de los modelos de bases de datos y los métodos de conjunto de preguntas para traducir los datos de su modelo en variables y estructuras simples para la plantilla.

La ejecución de una consulta relacionada en un modelo de una plantilla no es algo que normalmente se ve en una plantilla de Django, y hay una buena razón para esto. En este momento, puede parecer muy simple dividir los últimos tres elementos del conjunto de comentarios. Tenga en cuenta, sin embargo, que la base de datos no devolverá los resultados en ningún orden garantizado. Esto significa que, además de su sector, ahora también necesita agregar una cláusula order_by; simplemente no hay forma de expresar esto en una plantilla, ni debería haberlo. Es mejor pensar en la vista como la traducción entre su modelo y la plantilla, y permitir que el trabajo orientado a la base de datos se realice allí, en lugar de incrustarse en HTML.

En este caso, les animo a pasar una rebanada ordenó a la plantilla de la vista:

# take first three sorted descending 
comments = thread.comment_set.order_by('-something')[:3] 

context = Context({'comments':comments}) 
return HttpResponse(tmplt.render(context)) 

Si tiene que hacer el corte en rodajas en la plantilla, y que realmente no se preocupan por la clasificación los resultados, pasar una lista a la plantilla.El filtro slice estará feliz de hacer el corte en lonchas negativo:

comments = list(thread.comment_set.all()) 
context = Context('comments':comments) 

En la plantilla:

{% for comment in comments|slice:"-3:" %} 
+1

Lo que me gusta de la respuesta que obtuve y modifiqué fue que estoy tirando de mi tabla de hilos y luego de la plantilla sacando los comentarios respectivos para que Django haga el trabajo de extraer los comentarios correctos. Diré que no me importa el hecho de que saca todos y cada uno de los comentarios solo para cortarlos todos, excepto 3, funciona bien porque los saca a todos y los clasifico por su fecha de creación, ENTONCES los corté. . – TheLizardKing

+1

Si hubiera una consulta que pudiera escribir y que extrajera X hilos y sus respectivos * últimos * tres comentarios, estaría dorado. En cambio, hago esto. – TheLizardKing

+0

Te daría todos los + 1 si pudiera: -/15 Rep :( – TheLizardKing

9

No he visto el filtro dictsortreversed utiliza con demasiada frecuencia, y de acuerdo con la documentación que se necesita una clave para ordenar por

{% for comment in thread.comment_set.all|dictsortreversed:"name"|slice:"3" %} 
+0

Cambiar el "nombre" a "creado" hizo el truco, ¡gracias! – TheLizardKing

0

no puedes cortar la lista antes de pasarla a su plantilla?

1

Utilice el atributo "ordenar" de la clase Meta de la clase Comment para establecer el orden requerido de los elementos.

IMO templates no es el lugar adecuado para pedir su conjunto de datos. El pedido debe hacerse en Modelos o Vistas.

0

Puede revertir un queryset si ya está ordenado por "created". Entonces aquí hay una solución más rápida.

{% for comment in thread.comment_set.all.reverse|slice:":3" %} 

También si no lo desea en orden inverso.

{% for comment in thread.comment_set.all.reverse|slice:":3"|dictsort:"created" %} 

pesar de que debe seguir el consejo Jarrets Hardie arriba y hacer todo lo que la lógica de las vistas, en lugar de en las plantillas.

0

Necesité solo esto e hice una solución más completa, creo. Espero que la gente lo encuentre útil. La vista necesita encontrar la identificación del last inserted record (example here). Tienes que revertir el pedido y obtener la identificación (PK) del último registro nuevo ingresado, que ahora será el primer registro, fácil de encontrar ahora en la parte superior del montón ;-). Calcule el valor de identificación del límite inferior que desea, luego ordene desde la entrada más baja a la más nueva o última con este operador al final ... [n: m] (creo que es solo un operador de lista), descartando los registros no deseados, y luego presentarlo en orden normal. Para un ejemplo tablas django aquí está mi código:

def showLatestRels(request): 
    #This view shows the latest 15 entries in the Release table 
    LastInserted = Release.objects.order_by('-pk')[0] 
    UpperLimit = LastInserted.id 
    LowerLimit = UpperLimit - 15 
    RelTable = Release.objects.all() 
    tablevalslat = ReleaseTable(RelTable[LowerLimit:UpperLimit]) 
    RequestConfig(request).configure(tablevalslat) 
    return render(request, 'DCESrtap/latrels.html', {'tablevalslat': tablevalslat} 

)

montón de maneras de hacerlo, consulte Django docs Make/limit Queries
pero no podía conseguir la idea dictsort para trabajar ....