Django proporciona formas de alto y bajo nivel para ayudarlo a administrar datos paginados, es decir, datos que se dividen en varias páginas, con enlaces “Anterior / Siguiente”.
los Paginator
clase
Bajo el capó, todos los métodos de paginación usan el Paginator
clase. Hace todo el trabajo pesado de dividir un QuerySet
dentro Page
objetos.
Ejemplo
Dar Paginator
una lista de objetos, más la cantidad de elementos que le gustaría tener en cada página, y le brinda métodos para acceder a los elementos de cada página:
>>> from django.core.paginator import Paginator >>> objects = ['john', 'paul', 'george', 'ringo'] >>> p = Paginator(objects, 2) >>> p.count 4 >>> p.num_pages 2 >>> type(p.page_range) <class 'range_iterator'> >>> p.page_range range(1, 3) >>> page1 = p.page(1) >>> page1 <Page 1 of 2> >>> page1.object_list ['john', 'paul'] >>> page2 = p.page(2) >>> page2.object_list ['george', 'ringo'] >>> page2.has_next() False >>> page2.has_previous() True >>> page2.has_other_pages() True >>> page2.next_page_number() Traceback (most recent call last): ... EmptyPage: That page contains no results >>> page2.previous_page_number() 1 >>> page2.start_index() # The 1-based index of the first item on this page 3 >>> page2.end_index() # The 1-based index of the last item on this page 4 >>> p.page(0) Traceback (most recent call last): ... EmptyPage: That page number is less than 1 >>> p.page(3) Traceback (most recent call last): ... EmptyPage: That page contains no results
Nota
Tenga en cuenta que puede dar Paginator
una lista / tupla, un Django QuerySet
, o cualquier otro objeto con un count()
o __len__()
método. Al determinar el número de objetos contenidos en el objeto pasado, Paginator
primero intentará llamar count()
, luego vuelva a usar len()
si el objeto pasado no tiene count()
método. Esto permite que objetos como los de Django QuerySet
para usar un más eficiente count()
método cuando esté disponible.
Paginar un ListView
django.views.generic.list.ListView
proporciona una forma integrada de paginar la lista mostrada. Puede hacer esto agregando un paginate_by
atributo a su clase de vista, por ejemplo:
from django.views.generic import ListView from myapp.models import Contact class ContactListView(ListView): paginate_by = 2 model = Contact
Esto limita el número de objetos por página y agrega un paginator
y page_obj
al context
. Para permitir que sus usuarios naveguen entre páginas, agregue enlaces a la página anterior y siguiente, en su plantilla de esta manera:
{% for contact in page_obj %} {# Each "contact" is a Contact model object. #} {{ contact.full_name|upper }}<br> ... {% endfor %} <div class="pagination"> <span class="step-links"> {% if page_obj.has_previous %} <a href="?page=1">« first</a> <a href="?page={{ page_obj.previous_page_number }}">previous</a> {% endif %} <span class="current"> Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. </span> {% if page_obj.has_next %} <a href="?page={{ page_obj.next_page_number }}">next</a> <a href="?page={{ page_obj.paginator.num_pages }}">last »</a> {% endif %} </span> </div>
Utilizando Paginator
en una función de vista
Aquí hay un ejemplo usando Paginator
en una función de vista para paginar un conjunto de consultas:
from django.core.paginator import Paginator from django.shortcuts import render from myapp.models import Contact def listing(request): contact_list = Contact.objects.all() paginator = Paginator(contact_list, 25) # Show 25 contacts per page. page_number = request.GET.get('page') page_obj = paginator.get_page(page_number) return render(request, 'list.html', {'page_obj': page_obj})
En la plantilla list.html
, puede incluir la navegación entre páginas de la misma forma que en la plantilla para el ListView
encima.