Django class based views (VI) - Lists
En aquesta sisena entrega (que hi ha algú per aquí ho ja us heu dormit tots?) veurem com podem mostrar llistes d'objectes que sovint podem trobar amb els CRUD.
Per a mostrar llistats (paginats o no) Django ens proporciona la classe ListView
que es pot trobar a dango.views.generic.list
.
Aquesta classe és hereva de MultipleObjectTemplateResponseMixin
i de BaseListView
.
BaseListView
és el que la la feina, ja que és fill de MultipleObjectMixin
i de View
implementant-ne el mètode get.
Com les vistes orientades als CRUD també en aquest cas tenim una plantilla per defecte, formada pel nom del model i el sufixe '_list'.
El que més ens interessa són doncs els mètodes i atributs de MultipleObjectMixin
. Primer de tot, però anem a fer-ho fàcil, mostrarem la llista dels objectes que hem creat al post anterior:
A l'url:
url(r'^tutorial/sample/list/$', SampleListView.as_view(), name='tutorial_list_sample'),
i al views.py podem fer
from django.views.generic.list import ListView
class SampleListView(ListView):
model = Sample
i ara haurem de definir la plantilla que tindrà com a nom sample_list.html
, primer, però és convenient conèixer quines variables es passen al context, a saber:
- paginator
- page_obj
- is_paginated
- object_list
Els valors poden canviar en funció de si tenim paginació o no, però les variables que tenim són aquestes. El que ens interessa per ara és object_list
que conté la llista d'objectes del model. De manera que podem fer una plantilla del tipus:
<!DOCTYPE html PUBLIC "-//W3C//DTDT XHTML 1.1/EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"xml:lang>
<head>
<title>test</title>
</head>
<body>
<h1>Sample Detail List</h1>
<table border="1">
{% for sample in object_list %}
<tr>
<td><a href="{% url tutorial_update_sample sample.slug %}"> {{sample.slug}}</a><td/>
<td>{{sample.name}}<td/> <td>{{sample.ammount}}<td/>
<td>{{sample.comments}}<td/>
<td> <a href="{% url tutorial_delete_sample sample.slug %}">Delete</a>|<a href="{% url tutorial_create_sample %}">Create</a></td> </tr>
{% endfor %}
</tr>
</table>
</body>
</html>
Fixau-vos que no estic fent herència, l'html és molt simple etc. L'important aquí és veure com podem recórrer la llista d'objectes per montar les files d'una taula, i com amb el que ja sabem del CRUD podem enllaçar amb els manteniments.
Ara a l'hora de crear, editar o esborrar un registre podem elegir entre mostrar el registre o anar al llistat, afegint
success_url = reverse_lazy('tutorial_list_sample')
a les vistes que ens interessa ja ho tindriem.
Paginació
Com podem tenir molts resultats és comú que les llistes es mostrin paginades. Per fer això el que hem d'afegir l'atribut paginate_by
que ens determinarà el nombre màxim d'elements que es mostraran per plana.
class SampleListView(ListView):
model = Sample
paginate_by = 2
Si fem això i no modificam la plantilla, sols veurem dos registres, el que ens falta ara és afegir els controls de plana anterior i plana següent. Hi ham moltes maneres de fer la paginació i a la web en trobareu un bon munt, però per senzillesa aquest
{% if is_paginated %}
{% if page_obj.has_previous %}
<a href="{% url tutorial_list_sample %}?page={{ page_obj.previous_page_number }}">Previous> </a>
{% endif %}
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
{% if page_obj.has_next %}
<a href="{% url tutorial_list_sample %}?page={{ page_obj.next_page_number }}">Next </a>
{% endif %}
{% endif %}
Recordau que hem dit que al context es passava page_object
? Doncs fixau-vos com es fa servir per saber les propietats de la plana on estam, el nombre de planes total, si la plana té una plana anterior o una plana següent i el nombre corresponent a aquesta plana.
També fem us del is_paginated
de manera que no mostrem el selector de plana anterior i següent si sols hi ha una plana.
I ja ho tenim!
Al proper post, que tancarà la sèrie, veurem com podem limitar la informació que mostram als formularis d'edició