Paginação
Paginação é o processo de dividir uma grande lista de itens (exemplo: uma lista de receitas, posts, produtos, etc.) em várias páginas menores, para que o usuário visualize apenas um pedaço da lista por vez.
O Django já vem com uma ferramenta nativa para isso: django.core.paginator
Os principais elementos são:
| Componente | O que faz |
|---|---|
Paginator(queryset, n) |
Divide o queryset em páginas com até n itens |
page_obj = paginator.get_page(page_number) |
Pega a página específica |
page_obj.object_list |
Os itens dessa página (ex: 6 receitas) |
page_obj.has_next() |
Verifica se existe uma próxima página |
page_obj.has_previous() |
Verifica se existe uma página anterior |
paginator.num_pages |
Total de páginas |
| Paginação Django
pagination.py
import math
def make_pagination_range(
page_range,
qty_pages,
current_page,
):
middle_range = math.ceil(qty_pages / 2)
start_range = current_page - middle_range
stop_range = current_page + middle_range
total_pages = len(page_range)
start_range_offset = abs(start_range) if start_range < 0 else 0
if start_range < 0:
start_range = 0
stop_range += start_range_offset
if stop_range >= total_pages:
start_range = start_range - abs(total_pages - stop_range)
pagination = page_range[start_range:stop_range]
return {
'pagination': pagination,
'page_range': page_range,
'qty_pages': qty_pages,
'current_page': current_page,
'total_pages': total_pages,
'start_range': start_range,
'stop_range': stop_range,
'first_page_out_of_range': current_page > middle_range,
'last_page_out_of_range': stop_range < total_pages,
}
views_pagination.py
from django.core.paginator import Paginator
from django.shortcuts import render
from .models import Recipe
from .utils.pagination import make_pagination_range # ajuste o import conforme sua estrutura
def recipe_list_view(request):
recipes = Recipe.objects.all().order_by('-id') # Pegando todas as receitas
page_number = request.GET.get('page', 1) # Pegando o número da página via query string ?page=
paginator = Paginator(recipes, 6) # Exemplo: 6 receitas por página
page_obj = paginator.get_page(page_number) # Pega o objeto da página atual
pagination_range = make_pagination_range(
page_range=paginator.page_range, # Exemplo: range(1, total_pages+1)
qty_pages=5, # Quantidade máxima de botões de página que quer exibir (ex: 5 botões)
current_page=page_obj.number, # Página atual
)
context = {
'recipes': page_obj.object_list, # Lista de receitas desta página
'page_obj': page_obj, # Objeto da página (tem métodos úteis como has_next, has_previous)
'pagination_range': pagination_range, # Range customizado usando sua função
}
return render(request, 'recipes/recipe_list.html', context)
recipe_list.html
<h1>Lista de Receitas</h1>
<ul>
{% for recipe in recipes %}
<li>{{ recipe.title }}</li>
{% endfor %}
</ul>
<div class="pagination">
{% if page_obj.has_previous %}
<a href="?page=1">Primeira</a>
<a href="?page={{ page_obj.previous_page_number }}">Anterior</a>
{% endif %}
{% for page in pagination_range.pagination %}
{% if page == page_obj.number %}
<strong>{{ page }}</strong>
{% else %}
<a href="?page={{ page }}">{{ page }}</a>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">Próxima</a>
<a href="?page={{ page_obj.paginator.num_pages }}">Última</a>
{% endif %}
</div>