Paginación en Django con ListView
Hace justo una semana conseguí publicar mi post número 11 así que decidí que era hora de añadir una paginación a mi blog y aprovechar ese conocimiento para crear un post de paginación con Django. Me sorprendió lo sencillo que es implementarlo como vais a ver, ¡here we go!
Para este ejemplo he creado un proyecto que va a paginar el listado de países existentes. He creado un modelo que contendrá el iso code y el nombre del país, como podéis ver aquí.
from django.db import models
class Country(models.Model):
"""Country model."""
iso_code = models.CharField(max_length=2,unique=True)
name = models.CharField(max_length=255,unique=True)
class Meta:
ordering = ('iso_code',)
def __str__(self):
return self.name
Una vez hecho esto he realizado las migraciones e importé el listado de países a mi base de datos.
Lo siguiente que haremos será crear la vista, para este caso utilizaremos la vista genérica ListView que nos facilitará el trabajo.
# Country view
from django.shortcuts import render
from django.views.generic import ListView
# Models
from countries.models import Country
class CountriesFeedView(ListView):
template_name = 'countries/feed.html'
model = Country
paginate_by = 10
context_object_name = 'countries'
Aquí lo que estamos haciendo es importar primero la vista genérica ListView y el modelo Country que es el que vamos a usar.
Después creamos la clase que extenderá de ListView, en este caso CountriesFeedView y añadimos la configuración.
template_name: Es la url donde se encuentra la plantilla que vamos a utilizar.
model: Nombre del modelo que utilizaremos, en este caso el modelo Country que es el que importamos anteriormente.
paginate_by: El número de objetos que se mostrarán por página, en este caso queremos que se muestren 10 países por página.
context_object_name: El nombre del objeto en la plantilla.
Una vez hecho esto Django nos proveerá del objecto page_obj que podremos utilizarlo en la plantilla para tratar la paginación. Este objeto contiene las siguientes utilidades:
page_obj.has_previous: Verifica si hay una página anterior.
page_obj.has_next: Verifica si hay una página posterior.
page_obj.previous_page_number: Devuelve el número de la página anterior.
page_obj.next_page_number: Devuelve el número de la siguiente página.
page_obj.number: Devuelve el número de la página actual.
page_obj.paginator.num_pages: Devuelve el número total de páginas.
Y aquí podéis ver como lo he implementado.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Countries list</title>
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap" rel="stylesheet">
<style>
* {
font-family: "Roboto", Arial;
}
.main {
max-width: 600px;
margin: 0 auto;
text-align: center;
}
.table-grid {
display: grid;
grid-template-columns: 1fr 1fr 3fr;
border-top: 1px solid black;
border-right: 1px solid black;
margin-bottom: 1rem;
text-align: left;
}
.table-grid > span {
padding: 8px 4px;
border-left: 1px solid black;
border-bottom: 1px solid black;
}
a {
text-decoration: none;
color: #009FD2;
}
a:hover {
text-decoration: underline;
color: #0082AC;
}
</style>
</head>
<body>
<div class="main">
<div class="table-grid">
<span>
<strong>Id</strong>
</span>
<span>
<strong>Iso code</strong>
</span>
<span>
<strong>Country name</strong>
</span>
{% for country in countries %}
<span>
{{country.id}}
</span>
<span>
{{country.iso_code}}
</span>
<span>
{{country.name}}
</span>
{% endfor %}
</div>
<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>
</div>
</body>
</html>
Para más información podéis acceder a la documentación de Django. Si queréis clonar el ejemplo del proyecto con la paginación implementada lo podéis hacer desde mi GitHub.
Recordad que cualquier duda podéis ponerla en los comentarios :)
Espero que este post te ayude y como siempre, te recomiendo seguirme en Twitter para estar al tanto de los nuevo contenido. Ahora también puedes seguirme en Instagram donde estoy subiendo tips, tutoriales en vídeo e información sobre herramientas para developers.
Por último os dejo mi guía para aprender a trabajar con APIs donde explico todo el funcionamiento de una API, el protocolo HTTP y veremos como construir una API con arquitectura REST.
Nos leemos 👋.